@mastra/playground-ui 29.0.0-alpha.2 → 29.0.0-alpha.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.
- package/CHANGELOG.md +67 -0
- package/dist/index.cjs.js +275 -92
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.css +61 -64
- package/dist/index.es.js +277 -93
- package/dist/index.es.js.map +1 -1
- package/dist/src/domains/traces/components/traces-list-view.d.ts +5 -1
- package/dist/src/domains/traces/hooks/use-traces.d.ts +108 -8
- package/dist/src/ds/components/Button/Button.d.ts +1 -1
- package/dist/src/ds/components/Button/index.d.ts +0 -1
- package/dist/src/ds/components/DashboardCard/dashboard-card.stories.d.ts +1 -0
- package/dist/src/ds/components/MainSidebar/main-sidebar-nav-link.d.ts +0 -1
- package/dist/src/ds/components/SectionCard/section-card.stories.d.ts +1 -0
- package/package.json +7 -7
- package/dist/src/ds/components/Button/ButtonWithTooltip.d.ts +0 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,72 @@
|
|
|
1
1
|
# @mastra/playground-ui
|
|
2
2
|
|
|
3
|
+
## 29.0.0-alpha.3
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Removed `ButtonWithTooltip` from `@mastra/playground-ui`. Use `Button` with the `tooltip` prop instead. ([#16719](https://github.com/mastra-ai/mastra/pull/16719))
|
|
8
|
+
|
|
9
|
+
**Migration**
|
|
10
|
+
|
|
11
|
+
```tsx
|
|
12
|
+
// before
|
|
13
|
+
import { ButtonWithTooltip } from '@mastra/playground-ui';
|
|
14
|
+
|
|
15
|
+
<ButtonWithTooltip tooltipContent="Search">
|
|
16
|
+
<Search />
|
|
17
|
+
</ButtonWithTooltip>;
|
|
18
|
+
|
|
19
|
+
// after
|
|
20
|
+
import { Button } from '@mastra/playground-ui';
|
|
21
|
+
|
|
22
|
+
<Button tooltip="Search">
|
|
23
|
+
<Search />
|
|
24
|
+
</Button>;
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
`tooltip` supports the same values as `tooltipContent`. Icon-only buttons that pass a string `tooltip` now also get it as their `aria-label` automatically, matching how labelled controls have always behaved. Pass an explicit `aria-label` to override.
|
|
28
|
+
|
|
29
|
+
### Patch Changes
|
|
30
|
+
|
|
31
|
+
- The Traces list now updates live via delta polling. Previously the list was refetched every 10 seconds, replacing the whole page with no signal about what changed; now new traces appear within a few seconds of being created, with a brief highlight to draw attention. Status changes on already-visible rows (running → success / error) also propagate without intervention, and returning to the tab after being idle re-syncs from a fresh cursor. ([#16727](https://github.com/mastra-ai/mastra/pull/16727))
|
|
32
|
+
|
|
33
|
+
**New `useTraces` return fields**
|
|
34
|
+
- `isRefetching` — true while any meaningful refetch is in flight. Use it to drive a heartbeat indicator.
|
|
35
|
+
- `autoRefetch` / `setAutoRefetch` — pause / resume all automatic polling so the consumer can render an opt-out toggle.
|
|
36
|
+
- `recentlyAddedKeys` — `Set<string>` of `traceId:spanId` for rows that just arrived via delta polling. Drives the temporary highlight in `TracesListView`.
|
|
37
|
+
|
|
38
|
+
**New polling config**
|
|
39
|
+
|
|
40
|
+
Every timing in the hook is tunable per-instance via a new `polling` option:
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
import { useTraces, type TracesPollingConfig } from '@mastra/playground-ui';
|
|
44
|
+
|
|
45
|
+
useTraces({
|
|
46
|
+
filters,
|
|
47
|
+
listMode,
|
|
48
|
+
polling: {
|
|
49
|
+
deltaPollIntervalMs: 10_000,
|
|
50
|
+
idleGuardThresholdMs: 5 * 60_000,
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Omitted fields fall through to the defaults (delta poll every 5s, idle reset after 15 min, status refresh every 60s, etc).
|
|
56
|
+
|
|
57
|
+
**TracesListView**
|
|
58
|
+
|
|
59
|
+
New optional `recentlyAddedKeys?: Set<string>` prop. Rows whose `traceId:spanId` is in the set get the `animate-row-highlight` class — a brief fade-out to transparent, added to `index.css`.
|
|
60
|
+
|
|
61
|
+
**Compatibility**
|
|
62
|
+
|
|
63
|
+
Requires `@mastra/server` and `@mastra/client-js` at the versions that ship the observability delta-polling endpoints, and a store that opts into delta polling (`@mastra/clickhouse`, `@mastra/duckdb`, and the in-memory store today). When unavailable — older server or a store without delta capability — the hook silently falls back to page-mode interval refetching. No consumer changes required.
|
|
64
|
+
|
|
65
|
+
- Updated dependencies [[`5556cc1`](https://github.com/mastra-ai/mastra/commit/5556cc1befec71518d84f826b3bfe3a079a9daf7), [`5499303`](https://github.com/mastra-ai/mastra/commit/54993032c1ebc09642625b78d2014e0cf84a3cae), [`3498b49`](https://github.com/mastra-ai/mastra/commit/3498b4946be94f4313cd817733589680dcda5278), [`e47bca7`](https://github.com/mastra-ai/mastra/commit/e47bca7b72866d3abd173b9f530ac4318113a8ff), [`0031d0f`](https://github.com/mastra-ai/mastra/commit/0031d0f13831d7843ac5d498734a7d92862e2ce3), [`3498b49`](https://github.com/mastra-ai/mastra/commit/3498b4946be94f4313cd817733589680dcda5278), [`359439b`](https://github.com/mastra-ai/mastra/commit/359439bb8c635e048176306828195f8297f50021)]:
|
|
66
|
+
- @mastra/core@1.36.0-alpha.3
|
|
67
|
+
- @mastra/client-js@1.20.0-alpha.3
|
|
68
|
+
- @mastra/react@0.4.0-alpha.3
|
|
69
|
+
|
|
3
70
|
## 29.0.0-alpha.2
|
|
4
71
|
|
|
5
72
|
### Patch Changes
|
package/dist/index.cjs.js
CHANGED
|
@@ -3664,12 +3664,10 @@ const buttonVariants = cva(
|
|
|
3664
3664
|
{
|
|
3665
3665
|
variants: {
|
|
3666
3666
|
variant: {
|
|
3667
|
-
default: "bg-surface3 border border-
|
|
3668
|
-
primary: "bg-
|
|
3669
|
-
cta: "bg-accent1 border border-transparent hover:bg-accent1/90 hover:shadow-glow-accent1 disabled:hover:shadow-none text-surface1 font-medium",
|
|
3667
|
+
default: "bg-surface3 border border-border2 hover:bg-surface5 hover:text-neutral6 active:bg-surface6 text-neutral6",
|
|
3668
|
+
primary: "bg-neutral6 border border-transparent hover:bg-neutral6/90 active:bg-neutral6/80 text-surface1 font-medium",
|
|
3670
3669
|
ghost: "bg-transparent border border-transparent hover:bg-neutral6/5 hover:text-neutral6 active:bg-neutral6/10 text-neutral4",
|
|
3671
|
-
outline: "bg-transparent border border-border1 hover:bg-surface3 hover:text-neutral6 active:bg-surface4 text-neutral5"
|
|
3672
|
-
link: "inline-flex justify-start rounded-none h-auto px-0 bg-transparent text-neutral3 hover:text-neutral4 gap-1 [&>svg]:mx-0 w-auto [&>svg]:opacity-70"
|
|
3670
|
+
outline: "bg-transparent border border-border1 hover:bg-surface3 hover:text-neutral6 active:bg-surface4 text-neutral5"
|
|
3673
3671
|
},
|
|
3674
3672
|
size: {
|
|
3675
3673
|
sm: cn(`${formElementSizes.sm} text-ui-sm px-[.9em]`, TEXT_MODE_ADORNMENTS),
|
|
@@ -3742,16 +3740,6 @@ const Button = React.forwardRef(
|
|
|
3742
3740
|
);
|
|
3743
3741
|
Button.displayName = "Button";
|
|
3744
3742
|
|
|
3745
|
-
const ButtonWithTooltip = React.forwardRef(
|
|
3746
|
-
({ tooltipContent, ...buttonProps }, ref) => {
|
|
3747
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
|
|
3748
|
-
/* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(Button, { ref, ...buttonProps }) }),
|
|
3749
|
-
tooltipContent && /* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { children: tooltipContent })
|
|
3750
|
-
] });
|
|
3751
|
-
}
|
|
3752
|
-
);
|
|
3753
|
-
ButtonWithTooltip.displayName = "ButtonWithTooltip";
|
|
3754
|
-
|
|
3755
3743
|
function flattenSchemaToVariables(schema, maxDepth = 5) {
|
|
3756
3744
|
if (!schema?.properties) {
|
|
3757
3745
|
return [];
|
|
@@ -6938,7 +6926,7 @@ function HighlightedCode({ code, lang }) {
|
|
|
6938
6926
|
}
|
|
6939
6927
|
|
|
6940
6928
|
function DashboardCard({ children, className }) {
|
|
6941
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("border border-border1 rounded-
|
|
6929
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("border border-border1 rounded-xl px-4 py-3 bg-surface-overlay-soft", className), children });
|
|
6942
6930
|
}
|
|
6943
6931
|
|
|
6944
6932
|
const DropdownMenuRoot = DropdownMenuPrimitive__namespace.Root;
|
|
@@ -10842,7 +10830,7 @@ const navItemClasses = ({ isActive, isCollapsed, isFeatured } = {}) => cn(
|
|
|
10842
10830
|
"hover:bg-sidebar-nav-hover hover:text-neutral6 [&:hover_svg]:text-neutral5",
|
|
10843
10831
|
"focus-visible:outline-hidden focus-visible:ring-1 focus-visible:ring-accent1 focus-visible:shadow-focus-ring",
|
|
10844
10832
|
!isCollapsed && "w-full gap-2.5 py-1 px-3 justify-start",
|
|
10845
|
-
isCollapsed && "w-
|
|
10833
|
+
isCollapsed && "w-full p-0 justify-center",
|
|
10846
10834
|
isActive && "text-neutral6 bg-sidebar-nav-active hover:bg-sidebar-nav-active hover:text-neutral6 [&_svg]:text-neutral6 [&:hover_svg]:text-neutral6",
|
|
10847
10835
|
isCollapsed && !isActive && "[&_svg]:text-neutral3",
|
|
10848
10836
|
isFeatured && "my-2 bg-accent1Dark hover:bg-accent1Darker text-accent1 hover:text-accent1 border border-accent1/30",
|
|
@@ -10879,11 +10867,7 @@ function MainSidebarNavLink({
|
|
|
10879
10867
|
interactiveEl = /* @__PURE__ */ jsxRuntime.jsxs(Link, { href: link.url, ...linkParams, className: itemClassName, children: [
|
|
10880
10868
|
link.icon,
|
|
10881
10869
|
/* @__PURE__ */ jsxRuntime.jsx(MainSidebarNavLabel, { state, children: link.name }),
|
|
10882
|
-
children
|
|
10883
|
-
link.isExperimental && !isCollapsed && !needsTooltip && /* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
|
|
10884
|
-
/* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { render: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CircleAlertIcon, { className: "ml-auto stroke-accent5" }) }),
|
|
10885
|
-
/* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { side: "right", align: "center", sideOffset: 16, children: "Experimental Feature" })
|
|
10886
|
-
] })
|
|
10870
|
+
children
|
|
10887
10871
|
] });
|
|
10888
10872
|
}
|
|
10889
10873
|
return /* @__PURE__ */ jsxRuntime.jsx("li", { ...props, className: cn("flex relative min-w-0", className), children: link && needsTooltip && React.isValidElement(interactiveEl) ? /* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
|
|
@@ -11384,7 +11368,7 @@ function SectionCard({
|
|
|
11384
11368
|
className: cn(
|
|
11385
11369
|
"overflow-hidden rounded-2xl border",
|
|
11386
11370
|
fillHeight && "flex h-full flex-col",
|
|
11387
|
-
danger ? "border-accent2/25" : "border-
|
|
11371
|
+
danger ? "border-accent2/25" : "border-border1",
|
|
11388
11372
|
className
|
|
11389
11373
|
),
|
|
11390
11374
|
children: [
|
|
@@ -11393,7 +11377,7 @@ function SectionCard({
|
|
|
11393
11377
|
{
|
|
11394
11378
|
className: cn(
|
|
11395
11379
|
"flex flex-col gap-3 px-7 pt-7 pb-6 sm:flex-row sm:items-start sm:justify-between sm:gap-6",
|
|
11396
|
-
danger ? "bg-accent2/
|
|
11380
|
+
danger ? "bg-accent2/8" : "bg-surface-overlay-soft"
|
|
11397
11381
|
),
|
|
11398
11382
|
children: [
|
|
11399
11383
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-w-0", children: /* @__PURE__ */ jsxRuntime.jsx(CardHeading, { title, description, tone: danger ? "danger" : "default" }) }),
|
|
@@ -11407,7 +11391,7 @@ function SectionCard({
|
|
|
11407
11391
|
className: cn(
|
|
11408
11392
|
"min-w-0 px-7 pt-6 pb-7",
|
|
11409
11393
|
fillHeight && "flex-1",
|
|
11410
|
-
danger ? "bg-accent2/
|
|
11394
|
+
danger ? "bg-accent2/4" : null,
|
|
11411
11395
|
contentClassName
|
|
11412
11396
|
),
|
|
11413
11397
|
children
|
|
@@ -14286,25 +14270,16 @@ function DataCodeSection({
|
|
|
14286
14270
|
/* @__PURE__ */ jsxRuntime.jsxs(ButtonsGroup, { children: [
|
|
14287
14271
|
/* @__PURE__ */ jsxRuntime.jsx(CopyButton, { content: codeStr || "No content", size: "sm" }),
|
|
14288
14272
|
hasMultilineText && /* @__PURE__ */ jsxRuntime.jsx(
|
|
14289
|
-
|
|
14273
|
+
Button,
|
|
14290
14274
|
{
|
|
14291
14275
|
size: "sm",
|
|
14292
14276
|
"aria-label": showAsMultilineText ? "Show escaped newlines" : "Show multiline text",
|
|
14293
|
-
|
|
14277
|
+
tooltip: showAsMultilineText ? "Show escaped newlines" : "Show multiline text",
|
|
14294
14278
|
onClick: () => setShowAsMultilineText((v) => !v),
|
|
14295
14279
|
children: showAsMultilineText ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlignLeftIcon, {}) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlignJustifyIcon, {})
|
|
14296
14280
|
}
|
|
14297
14281
|
),
|
|
14298
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
14299
|
-
ButtonWithTooltip,
|
|
14300
|
-
{
|
|
14301
|
-
size: "sm",
|
|
14302
|
-
"aria-label": "Expand",
|
|
14303
|
-
tooltipContent: "Expand",
|
|
14304
|
-
onClick: () => setExpandedOpen(true),
|
|
14305
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ExpandIcon, {})
|
|
14306
|
-
}
|
|
14307
|
-
)
|
|
14282
|
+
/* @__PURE__ */ jsxRuntime.jsx(Button, { size: "sm", "aria-label": "Expand", tooltip: "Expand", onClick: () => setExpandedOpen(true), children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ExpandIcon, {}) })
|
|
14308
14283
|
] })
|
|
14309
14284
|
] })
|
|
14310
14285
|
] }),
|
|
@@ -14342,16 +14317,16 @@ function DataCodeSection({
|
|
|
14342
14317
|
/* @__PURE__ */ jsxRuntime.jsxs(ButtonsGroup, { children: [
|
|
14343
14318
|
/* @__PURE__ */ jsxRuntime.jsx(CopyButton, { content: codeStr || "No content", size: "sm" }),
|
|
14344
14319
|
hasMultilineText && /* @__PURE__ */ jsxRuntime.jsx(
|
|
14345
|
-
|
|
14320
|
+
Button,
|
|
14346
14321
|
{
|
|
14347
14322
|
size: "sm",
|
|
14348
14323
|
"aria-label": expandedMultiline ? "Show escaped newlines" : "Show multiline text",
|
|
14349
|
-
|
|
14324
|
+
tooltip: expandedMultiline ? "Show escaped newlines" : "Show multiline text",
|
|
14350
14325
|
onClick: () => setExpandedMultiline((v) => !v),
|
|
14351
14326
|
children: expandedMultiline ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlignLeftIcon, {}) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlignJustifyIcon, {})
|
|
14352
14327
|
}
|
|
14353
14328
|
),
|
|
14354
|
-
/* @__PURE__ */ jsxRuntime.jsx(DialogClose, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
14329
|
+
/* @__PURE__ */ jsxRuntime.jsx(DialogClose, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(Button, { size: "sm", "aria-label": "Close", tooltip: "Close", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.XIcon, {}) }) })
|
|
14355
14330
|
] })
|
|
14356
14331
|
] })
|
|
14357
14332
|
] }),
|
|
@@ -14398,17 +14373,7 @@ function DataDetailsPanelCloseButton({
|
|
|
14398
14373
|
tooltip = "Close panel",
|
|
14399
14374
|
className
|
|
14400
14375
|
}) {
|
|
14401
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
14402
|
-
ButtonWithTooltip,
|
|
14403
|
-
{
|
|
14404
|
-
size: "md",
|
|
14405
|
-
onClick,
|
|
14406
|
-
"aria-label": "Close Panel",
|
|
14407
|
-
tooltipContent: tooltip,
|
|
14408
|
-
className,
|
|
14409
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.XIcon, {})
|
|
14410
|
-
}
|
|
14411
|
-
);
|
|
14376
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Button, { size: "md", onClick, "aria-label": "Close Panel", tooltip, className, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.XIcon, {}) });
|
|
14412
14377
|
}
|
|
14413
14378
|
|
|
14414
14379
|
function buildDarkTheme() {
|
|
@@ -14711,17 +14676,7 @@ const DataKeysAndValues = Object.assign(DataKeysAndValuesRoot, {
|
|
|
14711
14676
|
});
|
|
14712
14677
|
|
|
14713
14678
|
function DataPanelCloseButton({ onClick, tooltip = "Close panel", className }) {
|
|
14714
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
14715
|
-
ButtonWithTooltip,
|
|
14716
|
-
{
|
|
14717
|
-
size: "md",
|
|
14718
|
-
onClick,
|
|
14719
|
-
"aria-label": "Close Panel",
|
|
14720
|
-
tooltipContent: tooltip,
|
|
14721
|
-
className,
|
|
14722
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.XIcon, {})
|
|
14723
|
-
}
|
|
14724
|
-
);
|
|
14679
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Button, { size: "md", onClick, "aria-label": "Close Panel", tooltip, className, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.XIcon, {}) });
|
|
14725
14680
|
}
|
|
14726
14681
|
|
|
14727
14682
|
function DataPanelContent({ children, ref }) {
|
|
@@ -14757,8 +14712,8 @@ function DataPanelNextPrevNav({
|
|
|
14757
14712
|
nextLabel = "Next"
|
|
14758
14713
|
}) {
|
|
14759
14714
|
return /* @__PURE__ */ jsxRuntime.jsxs(ButtonsGroup, { spacing: "close", children: [
|
|
14760
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
14761
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
14715
|
+
/* @__PURE__ */ jsxRuntime.jsx(Button, { size: "md", tooltip: previousLabel, onClick: onPrevious, disabled: !onPrevious, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUpIcon, {}) }),
|
|
14716
|
+
/* @__PURE__ */ jsxRuntime.jsx(Button, { size: "md", tooltip: nextLabel, onClick: onNext, disabled: !onNext, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowDownIcon, {}) })
|
|
14762
14717
|
] });
|
|
14763
14718
|
}
|
|
14764
14719
|
|
|
@@ -16808,13 +16763,13 @@ function StackedRunsBars({ data }) {
|
|
|
16808
16763
|
|
|
16809
16764
|
function OpenInTracesButton({ href, LinkComponent = "a" }) {
|
|
16810
16765
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
16811
|
-
|
|
16766
|
+
Button,
|
|
16812
16767
|
{
|
|
16813
16768
|
as: LinkComponent,
|
|
16814
16769
|
href,
|
|
16815
16770
|
variant: "ghost",
|
|
16816
16771
|
size: "icon-md",
|
|
16817
|
-
|
|
16772
|
+
tooltip: "View in Traces",
|
|
16818
16773
|
"aria-label": "View in Traces",
|
|
16819
16774
|
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.EyeIcon, {})
|
|
16820
16775
|
}
|
|
@@ -16822,13 +16777,13 @@ function OpenInTracesButton({ href, LinkComponent = "a" }) {
|
|
|
16822
16777
|
}
|
|
16823
16778
|
function OpenErrorsInLogsButton({ href, LinkComponent = "a" }) {
|
|
16824
16779
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
16825
|
-
|
|
16780
|
+
Button,
|
|
16826
16781
|
{
|
|
16827
16782
|
as: LinkComponent,
|
|
16828
16783
|
href,
|
|
16829
16784
|
variant: "ghost",
|
|
16830
16785
|
size: "icon-md",
|
|
16831
|
-
|
|
16786
|
+
tooltip: "View errors in Logs",
|
|
16832
16787
|
"aria-label": "View errors in Logs",
|
|
16833
16788
|
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.LogsIcon, {})
|
|
16834
16789
|
}
|
|
@@ -19592,10 +19547,10 @@ function TraceDataPanelView({
|
|
|
19592
19547
|
] }),
|
|
19593
19548
|
/* @__PURE__ */ jsxRuntime.jsxs(ButtonsGroup, { className: "ml-auto shrink-0", children: [
|
|
19594
19549
|
onCollapsedChange && /* @__PURE__ */ jsxRuntime.jsx(
|
|
19595
|
-
|
|
19550
|
+
Button,
|
|
19596
19551
|
{
|
|
19597
19552
|
size: "md",
|
|
19598
|
-
|
|
19553
|
+
tooltip: collapsed ? "Expand panel" : "Collapse panel",
|
|
19599
19554
|
onClick: () => setCollapsed(!collapsed),
|
|
19600
19555
|
children: collapsed ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronsUpDownIcon, {}) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronsDownUpIcon, {})
|
|
19601
19556
|
}
|
|
@@ -19610,12 +19565,12 @@ function TraceDataPanelView({
|
|
|
19610
19565
|
}
|
|
19611
19566
|
),
|
|
19612
19567
|
showOpenTracePageLink && /* @__PURE__ */ jsxRuntime.jsx(
|
|
19613
|
-
|
|
19568
|
+
Button,
|
|
19614
19569
|
{
|
|
19615
19570
|
as: LinkComponent,
|
|
19616
19571
|
href: traceHref,
|
|
19617
19572
|
size: "md",
|
|
19618
|
-
|
|
19573
|
+
tooltip: "Open trace page",
|
|
19619
19574
|
"aria-label": "Open trace page",
|
|
19620
19575
|
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Link2Icon, {})
|
|
19621
19576
|
}
|
|
@@ -20126,6 +20081,7 @@ function TracesListView({
|
|
|
20126
20081
|
featuredTraceId,
|
|
20127
20082
|
featuredSpanId,
|
|
20128
20083
|
isBranchesMode,
|
|
20084
|
+
recentlyAddedKeys,
|
|
20129
20085
|
onTraceClick
|
|
20130
20086
|
}) {
|
|
20131
20087
|
const scrollRef = React.useRef(null);
|
|
@@ -20169,6 +20125,8 @@ function TracesListView({
|
|
|
20169
20125
|
const trace = traces[vi.index];
|
|
20170
20126
|
if (!trace) return null;
|
|
20171
20127
|
const isFeatured = trace.traceId === featuredTraceId && (featuredSpanId == null || trace.spanId === featuredSpanId);
|
|
20128
|
+
const rowKey = `${trace.traceId}:${trace.spanId ?? ""}`;
|
|
20129
|
+
const isRecentlyAdded = recentlyAddedKeys?.has(rowKey) ?? false;
|
|
20172
20130
|
const displayDate = trace.startedAt ?? trace.createdAt;
|
|
20173
20131
|
const entityName = trace.entityName || trace.entityId || trace.attributes?.agentId || trace.attributes?.workflowId;
|
|
20174
20132
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -20177,7 +20135,7 @@ function TracesListView({
|
|
|
20177
20135
|
ref: virtualizer.measureElement,
|
|
20178
20136
|
"data-index": vi.index,
|
|
20179
20137
|
onClick: () => onTraceClick(trace),
|
|
20180
|
-
className: cn(isFeatured && "bg-surface4"),
|
|
20138
|
+
className: cn(isFeatured && "bg-surface4", isRecentlyAdded && "animate-row-highlight"),
|
|
20181
20139
|
children: [
|
|
20182
20140
|
/* @__PURE__ */ jsxRuntime.jsx(TracesDataList.DateCell, { timestamp: displayDate }),
|
|
20183
20141
|
/* @__PURE__ */ jsxRuntime.jsx(TracesDataList.TimeCell, { timestamp: displayDate }),
|
|
@@ -20194,7 +20152,7 @@ function TracesListView({
|
|
|
20194
20152
|
/* @__PURE__ */ jsxRuntime.jsx(TracesDataList.StatusCell, { status: trace.attributes?.status })
|
|
20195
20153
|
]
|
|
20196
20154
|
},
|
|
20197
|
-
|
|
20155
|
+
rowKey
|
|
20198
20156
|
);
|
|
20199
20157
|
}),
|
|
20200
20158
|
/* @__PURE__ */ jsxRuntime.jsx(TracesDataList.Spacer, { height: paddingBottom }),
|
|
@@ -20405,20 +20363,35 @@ function useTraceSpans(traceId) {
|
|
|
20405
20363
|
});
|
|
20406
20364
|
}
|
|
20407
20365
|
|
|
20366
|
+
const deltaSupportByClient = /* @__PURE__ */ new WeakMap();
|
|
20367
|
+
const DEFAULT_POLLING_CONFIG = {
|
|
20368
|
+
deltaPollIntervalMs: 5e3,
|
|
20369
|
+
deltaChaseIntervalMs: 100,
|
|
20370
|
+
deltaLimit: 100,
|
|
20371
|
+
pageModeRefetchIntervalMs: 1e4,
|
|
20372
|
+
page0StatusRefreshIntervalMs: 6e4,
|
|
20373
|
+
idleGuardThresholdMs: 15 * 6e4,
|
|
20374
|
+
minRefetchSpinMs: 400,
|
|
20375
|
+
deltaHighlightMs: 1e3
|
|
20376
|
+
};
|
|
20377
|
+
function shouldResetAfterIdle(lastSuccessAt, now, thresholdMs) {
|
|
20378
|
+
if (lastSuccessAt === 0) return false;
|
|
20379
|
+
return now - lastSuccessAt > thresholdMs;
|
|
20380
|
+
}
|
|
20381
|
+
function isHttp501(error) {
|
|
20382
|
+
return error?.status === 501;
|
|
20383
|
+
}
|
|
20408
20384
|
const fetchTracesFn = async ({
|
|
20409
20385
|
client,
|
|
20386
|
+
mode,
|
|
20410
20387
|
page,
|
|
20411
20388
|
perPage,
|
|
20389
|
+
after,
|
|
20390
|
+
limit,
|
|
20412
20391
|
filters,
|
|
20413
20392
|
listMode = "traces"
|
|
20414
20393
|
}) => {
|
|
20415
|
-
const params = {
|
|
20416
|
-
pagination: {
|
|
20417
|
-
page,
|
|
20418
|
-
perPage
|
|
20419
|
-
},
|
|
20420
|
-
filters
|
|
20421
|
-
};
|
|
20394
|
+
const params = mode === "delta" ? { mode: "delta", after, limit, filters } : { pagination: { page, perPage }, filters };
|
|
20422
20395
|
if (listMode === "branches") {
|
|
20423
20396
|
return client.listBranches(params);
|
|
20424
20397
|
}
|
|
@@ -20443,13 +20416,90 @@ function selectUniqueTraces(data) {
|
|
|
20443
20416
|
seen.add(key);
|
|
20444
20417
|
return true;
|
|
20445
20418
|
});
|
|
20446
|
-
return { spans };
|
|
20419
|
+
return { spans, deltaCursor: data.pages[0]?.deltaCursor };
|
|
20420
|
+
}
|
|
20421
|
+
function refreshPage0Rows(old, refreshed, listMode) {
|
|
20422
|
+
if (!old || old.pages.length === 0) return old;
|
|
20423
|
+
const [firstPage, ...rest] = old.pages;
|
|
20424
|
+
const refreshedRows = listMode === "branches" && "branches" in refreshed ? refreshed.branches ?? [] : "spans" in refreshed ? refreshed.spans ?? [] : [];
|
|
20425
|
+
if (refreshedRows.length === 0) return old;
|
|
20426
|
+
const refreshedByKey = /* @__PURE__ */ new Map();
|
|
20427
|
+
for (const row of refreshedRows) {
|
|
20428
|
+
refreshedByKey.set(`${row.traceId}:${row.spanId}`, row);
|
|
20429
|
+
}
|
|
20430
|
+
let updatedFirst;
|
|
20431
|
+
if (listMode === "branches" && "branches" in firstPage) {
|
|
20432
|
+
const updated = (firstPage.branches ?? []).map((existing) => {
|
|
20433
|
+
const fresh = refreshedByKey.get(`${existing.traceId}:${existing.spanId}`);
|
|
20434
|
+
return fresh ?? existing;
|
|
20435
|
+
});
|
|
20436
|
+
updatedFirst = { ...firstPage, branches: updated };
|
|
20437
|
+
} else if ("spans" in firstPage) {
|
|
20438
|
+
const updated = (firstPage.spans ?? []).map((existing) => {
|
|
20439
|
+
const fresh = refreshedByKey.get(`${existing.traceId}:${existing.spanId}`);
|
|
20440
|
+
return fresh ?? existing;
|
|
20441
|
+
});
|
|
20442
|
+
updatedFirst = { ...firstPage, spans: updated };
|
|
20443
|
+
} else {
|
|
20444
|
+
return old;
|
|
20445
|
+
}
|
|
20446
|
+
return { ...old, pages: [updatedFirst, ...rest] };
|
|
20447
|
+
}
|
|
20448
|
+
function sortRowsByStartedAtDesc(rows) {
|
|
20449
|
+
return [...rows].sort((a, b) => {
|
|
20450
|
+
const aTime = a.startedAt ? new Date(a.startedAt).getTime() : 0;
|
|
20451
|
+
const bTime = b.startedAt ? new Date(b.startedAt).getTime() : 0;
|
|
20452
|
+
return bTime - aTime;
|
|
20453
|
+
});
|
|
20454
|
+
}
|
|
20455
|
+
function mergeDeltaIntoPage0(old, delta, listMode) {
|
|
20456
|
+
if (!old || old.pages.length === 0) return old;
|
|
20457
|
+
const [firstPage, ...rest] = old.pages;
|
|
20458
|
+
const nextCursor = delta.deltaCursor ?? firstPage.deltaCursor;
|
|
20459
|
+
let updatedFirst;
|
|
20460
|
+
if (listMode === "branches" && "branches" in firstPage) {
|
|
20461
|
+
const newRows = delta.branches ?? [];
|
|
20462
|
+
updatedFirst = {
|
|
20463
|
+
...firstPage,
|
|
20464
|
+
branches: sortRowsByStartedAtDesc([...newRows, ...firstPage.branches ?? []]),
|
|
20465
|
+
deltaCursor: nextCursor
|
|
20466
|
+
};
|
|
20467
|
+
} else if ("spans" in firstPage) {
|
|
20468
|
+
const newRows = delta.spans ?? [];
|
|
20469
|
+
updatedFirst = {
|
|
20470
|
+
...firstPage,
|
|
20471
|
+
spans: sortRowsByStartedAtDesc([...newRows, ...firstPage.spans ?? []]),
|
|
20472
|
+
deltaCursor: nextCursor
|
|
20473
|
+
};
|
|
20474
|
+
} else {
|
|
20475
|
+
return old;
|
|
20476
|
+
}
|
|
20477
|
+
return { ...old, pages: [updatedFirst, ...rest] };
|
|
20447
20478
|
}
|
|
20448
|
-
const useTraces = ({ filters, listMode = "traces" }) => {
|
|
20479
|
+
const useTraces = ({ filters, listMode = "traces", polling = {} }) => {
|
|
20480
|
+
const {
|
|
20481
|
+
deltaPollIntervalMs = DEFAULT_POLLING_CONFIG.deltaPollIntervalMs,
|
|
20482
|
+
deltaChaseIntervalMs = DEFAULT_POLLING_CONFIG.deltaChaseIntervalMs,
|
|
20483
|
+
deltaLimit = DEFAULT_POLLING_CONFIG.deltaLimit,
|
|
20484
|
+
pageModeRefetchIntervalMs = DEFAULT_POLLING_CONFIG.pageModeRefetchIntervalMs,
|
|
20485
|
+
page0StatusRefreshIntervalMs = DEFAULT_POLLING_CONFIG.page0StatusRefreshIntervalMs,
|
|
20486
|
+
idleGuardThresholdMs = DEFAULT_POLLING_CONFIG.idleGuardThresholdMs,
|
|
20487
|
+
minRefetchSpinMs = DEFAULT_POLLING_CONFIG.minRefetchSpinMs,
|
|
20488
|
+
deltaHighlightMs = DEFAULT_POLLING_CONFIG.deltaHighlightMs
|
|
20489
|
+
} = polling;
|
|
20449
20490
|
const client = react.useMastraClient();
|
|
20491
|
+
const queryClient = reactQuery.useQueryClient();
|
|
20450
20492
|
const { inView: isEndOfListInView, setRef: setEndOfListElement } = useInView();
|
|
20493
|
+
const [deltaSupport, setDeltaSupport] = React.useState(() => deltaSupportByClient.get(client) ?? "unknown");
|
|
20494
|
+
const deltaUnsupported = deltaSupport === "unsupported";
|
|
20495
|
+
const [autoRefetch, setAutoRefetch] = React.useState(true);
|
|
20496
|
+
const [recentlyAddedKeys, setRecentlyAddedKeys] = React.useState(() => /* @__PURE__ */ new Set());
|
|
20497
|
+
React.useEffect(() => {
|
|
20498
|
+
setRecentlyAddedKeys(/* @__PURE__ */ new Set());
|
|
20499
|
+
}, [listMode, filters]);
|
|
20500
|
+
const tracesQueryKey = ["traces", listMode, filters];
|
|
20451
20501
|
const query = reactQuery.useInfiniteQuery({
|
|
20452
|
-
queryKey:
|
|
20502
|
+
queryKey: tracesQueryKey,
|
|
20453
20503
|
queryFn: ({ pageParam }) => fetchTracesFn({
|
|
20454
20504
|
client,
|
|
20455
20505
|
page: pageParam,
|
|
@@ -20461,16 +20511,150 @@ const useTraces = ({ filters, listMode = "traces" }) => {
|
|
|
20461
20511
|
getNextPageParam: getTracesNextPageParam,
|
|
20462
20512
|
select: selectUniqueTraces,
|
|
20463
20513
|
retry: false,
|
|
20464
|
-
// Disable polling on 403 to prevent flickering
|
|
20465
|
-
|
|
20514
|
+
// Disable polling on 403 to prevent flickering.
|
|
20515
|
+
// Fall back to page-mode polling only when delta isn't running.
|
|
20516
|
+
refetchInterval: (q) => {
|
|
20517
|
+
if (is403ForbiddenError(q.state.error)) return false;
|
|
20518
|
+
if (!autoRefetch) return false;
|
|
20519
|
+
return deltaUnsupported ? pageModeRefetchIntervalMs : false;
|
|
20520
|
+
}
|
|
20466
20521
|
});
|
|
20522
|
+
const cursor = query.data?.deltaCursor;
|
|
20523
|
+
React.useEffect(() => {
|
|
20524
|
+
if (query.isSuccess && cursor === void 0 && deltaSupport === "unknown") {
|
|
20525
|
+
deltaSupportByClient.set(client, "unsupported");
|
|
20526
|
+
setDeltaSupport("unsupported");
|
|
20527
|
+
}
|
|
20528
|
+
}, [query.isSuccess, cursor, deltaSupport, client]);
|
|
20529
|
+
const deltaQuery = reactQuery.useQuery({
|
|
20530
|
+
queryKey: ["traces-delta", listMode, filters],
|
|
20531
|
+
queryFn: () => {
|
|
20532
|
+
const current = queryClient.getQueryData(tracesQueryKey)?.pages[0]?.deltaCursor;
|
|
20533
|
+
if (!current) return null;
|
|
20534
|
+
return fetchTracesFn({
|
|
20535
|
+
client,
|
|
20536
|
+
mode: "delta",
|
|
20537
|
+
after: current,
|
|
20538
|
+
limit: deltaLimit,
|
|
20539
|
+
filters,
|
|
20540
|
+
listMode
|
|
20541
|
+
});
|
|
20542
|
+
},
|
|
20543
|
+
enabled: !!cursor && !deltaUnsupported && autoRefetch,
|
|
20544
|
+
retry: false,
|
|
20545
|
+
refetchInterval: (q) => {
|
|
20546
|
+
if (q.state.error) return false;
|
|
20547
|
+
const data = q.state.data;
|
|
20548
|
+
if (data?.delta?.hasMore) return deltaChaseIntervalMs;
|
|
20549
|
+
return deltaPollIntervalMs;
|
|
20550
|
+
}
|
|
20551
|
+
});
|
|
20552
|
+
React.useEffect(() => {
|
|
20553
|
+
const result = deltaQuery.data;
|
|
20554
|
+
if (!result) return;
|
|
20555
|
+
queryClient.setQueryData(
|
|
20556
|
+
tracesQueryKey,
|
|
20557
|
+
(old) => mergeDeltaIntoPage0(old, result, listMode)
|
|
20558
|
+
);
|
|
20559
|
+
const newRows = listMode === "branches" && "branches" in result ? result.branches ?? [] : "spans" in result ? result.spans ?? [] : [];
|
|
20560
|
+
if (newRows.length === 0) return;
|
|
20561
|
+
const keys = newRows.map((r) => `${r.traceId}:${r.spanId ?? ""}`);
|
|
20562
|
+
setRecentlyAddedKeys((prev) => {
|
|
20563
|
+
const next = new Set(prev);
|
|
20564
|
+
for (const k of keys) next.add(k);
|
|
20565
|
+
return next;
|
|
20566
|
+
});
|
|
20567
|
+
setTimeout(() => {
|
|
20568
|
+
setRecentlyAddedKeys((prev) => {
|
|
20569
|
+
const next = new Set(prev);
|
|
20570
|
+
for (const k of keys) next.delete(k);
|
|
20571
|
+
return next;
|
|
20572
|
+
});
|
|
20573
|
+
}, deltaHighlightMs);
|
|
20574
|
+
}, [deltaQuery.data, queryClient, listMode, filters, deltaHighlightMs]);
|
|
20575
|
+
React.useEffect(() => {
|
|
20576
|
+
if (isHttp501(deltaQuery.error)) {
|
|
20577
|
+
deltaSupportByClient.set(client, "unsupported");
|
|
20578
|
+
setDeltaSupport("unsupported");
|
|
20579
|
+
}
|
|
20580
|
+
}, [deltaQuery.error, client]);
|
|
20581
|
+
const statusRefreshQuery = reactQuery.useQuery({
|
|
20582
|
+
queryKey: ["traces-status-refresh", listMode, filters],
|
|
20583
|
+
queryFn: () => fetchTracesFn({
|
|
20584
|
+
client,
|
|
20585
|
+
page: 0,
|
|
20586
|
+
perPage: TRACES_PER_PAGE,
|
|
20587
|
+
filters,
|
|
20588
|
+
listMode
|
|
20589
|
+
}),
|
|
20590
|
+
enabled: !!cursor && !deltaUnsupported && autoRefetch,
|
|
20591
|
+
refetchInterval: page0StatusRefreshIntervalMs,
|
|
20592
|
+
refetchOnMount: false,
|
|
20593
|
+
retry: false
|
|
20594
|
+
});
|
|
20595
|
+
React.useEffect(() => {
|
|
20596
|
+
const result = statusRefreshQuery.data;
|
|
20597
|
+
if (!result) return;
|
|
20598
|
+
queryClient.setQueryData(
|
|
20599
|
+
tracesQueryKey,
|
|
20600
|
+
(old) => refreshPage0Rows(old, result, listMode)
|
|
20601
|
+
);
|
|
20602
|
+
}, [statusRefreshQuery.data, queryClient, listMode, filters]);
|
|
20603
|
+
const lastSuccessAtRef = React.useRef(0);
|
|
20604
|
+
React.useEffect(() => {
|
|
20605
|
+
const ts = Math.max(query.dataUpdatedAt, deltaQuery.dataUpdatedAt, statusRefreshQuery.dataUpdatedAt);
|
|
20606
|
+
if (ts > lastSuccessAtRef.current) {
|
|
20607
|
+
lastSuccessAtRef.current = ts;
|
|
20608
|
+
}
|
|
20609
|
+
}, [query.dataUpdatedAt, deltaQuery.dataUpdatedAt, statusRefreshQuery.dataUpdatedAt]);
|
|
20610
|
+
const autoRefetchRef = React.useRef(autoRefetch);
|
|
20611
|
+
React.useEffect(() => {
|
|
20612
|
+
autoRefetchRef.current = autoRefetch;
|
|
20613
|
+
}, [autoRefetch]);
|
|
20614
|
+
React.useEffect(() => {
|
|
20615
|
+
const handler = () => {
|
|
20616
|
+
if (document.visibilityState !== "visible") return;
|
|
20617
|
+
if (!autoRefetchRef.current) return;
|
|
20618
|
+
if (!shouldResetAfterIdle(lastSuccessAtRef.current, Date.now(), idleGuardThresholdMs)) return;
|
|
20619
|
+
void queryClient.resetQueries({ queryKey: ["traces", listMode, filters] });
|
|
20620
|
+
};
|
|
20621
|
+
document.addEventListener("visibilitychange", handler);
|
|
20622
|
+
return () => document.removeEventListener("visibilitychange", handler);
|
|
20623
|
+
}, [queryClient, listMode, filters, idleGuardThresholdMs]);
|
|
20467
20624
|
const { hasNextPage, isFetchingNextPage, fetchNextPage } = query;
|
|
20468
20625
|
React.useEffect(() => {
|
|
20469
20626
|
if (isEndOfListInView && hasNextPage && !isFetchingNextPage) {
|
|
20470
20627
|
void fetchNextPage();
|
|
20471
20628
|
}
|
|
20472
20629
|
}, [isEndOfListInView, hasNextPage, isFetchingNextPage, fetchNextPage]);
|
|
20473
|
-
|
|
20630
|
+
const isFetchingAny = query.isFetching || statusRefreshQuery.isFetching || deltaQuery.isFetching;
|
|
20631
|
+
const lastActivityAt = Math.max(
|
|
20632
|
+
query.dataUpdatedAt,
|
|
20633
|
+
query.errorUpdatedAt,
|
|
20634
|
+
deltaQuery.dataUpdatedAt,
|
|
20635
|
+
deltaQuery.errorUpdatedAt,
|
|
20636
|
+
statusRefreshQuery.dataUpdatedAt,
|
|
20637
|
+
statusRefreshQuery.errorUpdatedAt
|
|
20638
|
+
);
|
|
20639
|
+
const [pulse, setPulse] = React.useState(false);
|
|
20640
|
+
const prevActivityAtRef = React.useRef(lastActivityAt);
|
|
20641
|
+
React.useEffect(() => {
|
|
20642
|
+
if (lastActivityAt > prevActivityAtRef.current) {
|
|
20643
|
+
prevActivityAtRef.current = lastActivityAt;
|
|
20644
|
+
setPulse(true);
|
|
20645
|
+
const t = setTimeout(() => setPulse(false), minRefetchSpinMs);
|
|
20646
|
+
return () => clearTimeout(t);
|
|
20647
|
+
}
|
|
20648
|
+
}, [lastActivityAt, minRefetchSpinMs]);
|
|
20649
|
+
const isRefetching = isFetchingAny || pulse;
|
|
20650
|
+
return {
|
|
20651
|
+
...query,
|
|
20652
|
+
setEndOfListElement,
|
|
20653
|
+
isRefetching,
|
|
20654
|
+
autoRefetch,
|
|
20655
|
+
setAutoRefetch,
|
|
20656
|
+
recentlyAddedKeys
|
|
20657
|
+
};
|
|
20474
20658
|
};
|
|
20475
20659
|
|
|
20476
20660
|
const useTags = () => {
|
|
@@ -20939,17 +21123,17 @@ function LogDetailsView({
|
|
|
20939
21123
|
] }),
|
|
20940
21124
|
/* @__PURE__ */ jsxRuntime.jsxs(ButtonsGroup, { className: "ml-auto shrink-0", children: [
|
|
20941
21125
|
onCollapsedChange && /* @__PURE__ */ jsxRuntime.jsx(
|
|
20942
|
-
|
|
21126
|
+
Button,
|
|
20943
21127
|
{
|
|
20944
21128
|
size: "md",
|
|
20945
|
-
|
|
21129
|
+
tooltip: collapsed ? "Expand panel" : "Collapse panel",
|
|
20946
21130
|
onClick: () => setCollapsed(!collapsed),
|
|
20947
21131
|
children: collapsed ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronsUpDownIcon, {}) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronsDownUpIcon, {})
|
|
20948
21132
|
}
|
|
20949
21133
|
),
|
|
20950
21134
|
/* @__PURE__ */ jsxRuntime.jsxs(ButtonsGroup, { spacing: "close", children: [
|
|
20951
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
20952
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
21135
|
+
/* @__PURE__ */ jsxRuntime.jsx(Button, { size: "md", tooltip: "Previous log", onClick: onPrevious, disabled: !onPrevious, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUpIcon, {}) }),
|
|
21136
|
+
/* @__PURE__ */ jsxRuntime.jsx(Button, { size: "md", tooltip: "Next log", onClick: onNext, disabled: !onNext, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowDownIcon, {}) })
|
|
20953
21137
|
] }),
|
|
20954
21138
|
/* @__PURE__ */ jsxRuntime.jsx(DataDetailsPanel.CloseButton, { onClick: onClose })
|
|
20955
21139
|
] })
|
|
@@ -21638,7 +21822,6 @@ exports.BranchIcon = BranchIcon;
|
|
|
21638
21822
|
exports.BrandLoader = BrandLoader;
|
|
21639
21823
|
exports.Breadcrumb = Breadcrumb;
|
|
21640
21824
|
exports.Button = Button;
|
|
21641
|
-
exports.ButtonWithTooltip = ButtonWithTooltip;
|
|
21642
21825
|
exports.ButtonsGroup = ButtonsGroup;
|
|
21643
21826
|
exports.ButtonsGroupSeparator = ButtonsGroupSeparator;
|
|
21644
21827
|
exports.ButtonsGroupText = ButtonsGroupText;
|