@mastra/playground-ui 31.0.0-alpha.6 → 31.0.0-alpha.8

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 CHANGED
@@ -1,5 +1,60 @@
1
1
  # @mastra/playground-ui
2
2
 
3
+ ## 31.0.0-alpha.8
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [[`0c1ed1d`](https://github.com/mastra-ai/mastra/commit/0c1ed1d00c7d87b5ac99ca95896211a2fa9189fa), [`849efb9`](https://github.com/mastra-ai/mastra/commit/849efb9fca6dc976589c1f90a303fea618769109)]:
8
+ - @mastra/core@1.38.0-alpha.8
9
+ - @mastra/client-js@1.22.0-alpha.8
10
+ - @mastra/react@0.4.3-alpha.8
11
+
12
+ ## 31.0.0-alpha.7
13
+
14
+ ### Patch Changes
15
+
16
+ - Added a `DataPanel.SectionHeading` component for small-caps section labels (with an optional leading icon) inside a `DataPanel.Content`. `DataCodeSection` now renders through it, and `DataPanel.Header` hides its bottom border when the panel is collapsed (header-only) so an empty panel no longer shows a stray divider. ([#17464](https://github.com/mastra-ai/mastra/pull/17464))
17
+
18
+ ```tsx
19
+ <DataPanel.SectionHeading icon={<FileInputIcon />}>Input</DataPanel.SectionHeading>
20
+ ```
21
+
22
+ - Changed `Spinner` to render the new compact loader by default and added `variant="pulse"` for longer data-loading states. Removed the `color` prop so the loader defaults to the neutral text token and color overrides go through `className`. ([#17455](https://github.com/mastra-ai/mastra/pull/17455))
23
+
24
+ **Migration note**
25
+
26
+ Before:
27
+
28
+ ```tsx
29
+ <Spinner color={Colors.neutral3} />
30
+ ```
31
+
32
+ After:
33
+
34
+ ```tsx
35
+ <Spinner className="text-neutral3" />
36
+ <Spinner variant="pulse" className="text-neutral1" />
37
+ ```
38
+
39
+ - Added an `is404NotFoundError` helper to detect 404 Not Found responses from the Mastra client, alongside the existing `is401UnauthorizedError` and `is403ForbiddenError` helpers. Use it to show a clear not-found state when a resource no longer exists. ([#17460](https://github.com/mastra-ai/mastra/pull/17460))
40
+
41
+ ```ts
42
+ import { is404NotFoundError } from '@mastra/playground-ui';
43
+
44
+ try {
45
+ await client.getDataset(id);
46
+ } catch (error) {
47
+ if (is404NotFoundError(error)) {
48
+ // show a not-found state instead of a generic error
49
+ }
50
+ }
51
+ ```
52
+
53
+ - Updated dependencies:
54
+ - @mastra/core@1.38.0-alpha.7
55
+ - @mastra/client-js@1.22.0-alpha.7
56
+ - @mastra/react@0.4.3-alpha.7
57
+
3
58
  ## 31.0.0-alpha.6
4
59
 
5
60
  ### Patch Changes
package/dist/index.cjs.js CHANGED
@@ -3414,7 +3414,7 @@ const focusRing = {
3414
3414
  visible: "focus-visible:outline-hidden focus-visible:ring-1 focus-visible:ring-accent1 focus-visible:shadow-focus-ring"
3415
3415
  };
3416
3416
 
3417
- const sizeClasses$4 = {
3417
+ const sizeClasses$3 = {
3418
3418
  sm: "h-avatar-sm w-avatar-sm",
3419
3419
  md: "h-avatar-md w-avatar-md",
3420
3420
  lg: "h-avatar-lg w-avatar-lg"
@@ -3428,7 +3428,7 @@ const Avatar = ({ src, name, size = "sm", interactive = false, color, textColor
3428
3428
  "div",
3429
3429
  {
3430
3430
  className: cn(
3431
- sizeClasses$4[size],
3431
+ sizeClasses$3[size],
3432
3432
  "border border-border1 shrink-0 overflow-hidden rounded-full flex items-center justify-center",
3433
3433
  !showFallbackTint && "bg-surface3",
3434
3434
  transitions.all,
@@ -5880,7 +5880,7 @@ const LogoWithoutText = (props) => /* @__PURE__ */ jsxRuntime.jsx("svg", { xmlns
5880
5880
  ) });
5881
5881
 
5882
5882
  const PATH_D = "M4.49805 11.6934C6.98237 11.6934 8.99609 13.7081 8.99609 16.1924C8.9959 18.6765 6.98225 20.6904 4.49805 20.6904C2.01394 20.6903 0.000196352 18.6765 0 16.1924C0 13.7081 2.01382 11.6935 4.49805 11.6934ZM10.3867 0C12.8709 0 14.8846 2.01388 14.8848 4.49805C14.8848 4.8377 14.847 5.16846 14.7755 5.48643C14.4618 6.88139 14.1953 8.4633 14.9928 9.65L16.2575 11.5319C16.3363 11.6491 16.4727 11.7115 16.6137 11.703C16.7369 11.6957 16.8525 11.6343 16.9214 11.5318L18.1876 9.64717C18.9772 8.47198 18.7236 6.90783 18.4205 5.52484C18.3523 5.21392 18.3164 4.89094 18.3164 4.55957C18.3167 2.07546 20.3313 0.0615234 22.8154 0.0615234C25.2994 0.0617476 27.3132 2.0756 27.3135 4.55957C27.3135 4.93883 27.2665 5.30712 27.178 5.65896C26.8547 6.94441 26.5817 8.37932 27.2446 9.52714L28.459 11.6301C28.4819 11.6697 28.5245 11.6934 28.5703 11.6934C31.0545 11.6935 33.0684 13.7081 33.0684 16.1924C33.0682 18.6765 31.0544 20.6903 28.5703 20.6904C26.0861 20.6904 24.0725 18.6765 24.0723 16.1924C24.0723 15.8049 24.1212 15.4288 24.2133 15.0701C24.5458 13.7746 24.8298 12.3251 24.1609 11.1668L23.0044 9.16384C22.9656 9.09659 22.8931 9.05859 22.8154 9.05859C22.7983 9.05859 22.7824 9.06614 22.7728 9.08033L21.4896 10.9895C20.686 12.1851 20.9622 13.781 21.284 15.1851C21.3582 15.5089 21.3975 15.8461 21.3975 16.1924C21.3973 18.6764 19.3834 20.6902 16.8994 20.6904C14.4152 20.6904 12.4006 18.6765 12.4004 16.1924C12.4004 15.932 12.4226 15.6768 12.4651 15.4286C12.6859 14.14 12.8459 12.7122 12.1167 11.6271L11.2419 10.3253C10.6829 9.49347 9.71913 9.05932 8.78286 8.70188C7.0906 8.05584 5.88867 6.41734 5.88867 4.49805C5.88886 2.0139 7.90254 3.29835e-05 10.3867 0Z";
5883
- const sizeClasses$3 = {
5883
+ const sizeClasses$2 = {
5884
5884
  sm: "w-6",
5885
5885
  md: "w-10"
5886
5886
  };
@@ -5909,7 +5909,7 @@ function Logo({ className, size = "md", animateOnHover = false, "aria-label": ar
5909
5909
  onAnimationEnd: handleAnimationEnd,
5910
5910
  className: cn(
5911
5911
  "logo inline-block text-neutral6",
5912
- sizeClasses$3[size],
5912
+ sizeClasses$2[size],
5913
5913
  animateOnHover && playing && "logo-animate-on-hover",
5914
5914
  className
5915
5915
  ),
@@ -8452,33 +8452,53 @@ function MetricsCardError({
8452
8452
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex flex-col gap-3 items-center justify-center", className), children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-ui-sm text-accent2", children: message }) });
8453
8453
  }
8454
8454
 
8455
- const sizeClasses$2 = {
8456
- sm: "w-4 h-4",
8457
- md: "w-6 h-6",
8458
- lg: "w-8 h-8"
8459
- };
8460
- function Spinner({ color, className, size = "md" }) {
8455
+ const spinnerVariants = cva("spinner inline-block text-neutral6", {
8456
+ variants: {
8457
+ size: {
8458
+ sm: "w-4 h-4",
8459
+ md: "w-6 h-6"
8460
+ },
8461
+ variant: {
8462
+ default: "",
8463
+ pulse: ""
8464
+ }
8465
+ },
8466
+ defaultVariants: {
8467
+ size: "md",
8468
+ variant: "default"
8469
+ }
8470
+ });
8471
+ function Spinner({
8472
+ className,
8473
+ size = "md",
8474
+ variant = "default",
8475
+ "aria-label": ariaLabel = "Loading",
8476
+ role = "status",
8477
+ ...props
8478
+ }) {
8479
+ const resolvedSize = size ?? "md";
8480
+ const resolvedVariant = variant ?? "default";
8461
8481
  return /* @__PURE__ */ jsxRuntime.jsx(
8462
8482
  "svg",
8463
8483
  {
8464
- className: cn("animate-spin", sizeClasses$2[size], className),
8465
- style: { animationDuration: "800ms", animationTimingFunction: "cubic-bezier(0.4, 0, 0.2, 1)" },
8484
+ ...props,
8485
+ role,
8486
+ "aria-label": ariaLabel,
8487
+ "data-size": resolvedSize,
8488
+ "data-variant": resolvedVariant,
8489
+ className: cn(spinnerVariants({ size: resolvedSize, variant: resolvedVariant }), className),
8466
8490
  xmlns: "http://www.w3.org/2000/svg",
8467
- width: "24",
8468
- height: "24",
8469
8491
  viewBox: "0 0 24 24",
8470
- fill: "none",
8471
- stroke: "currentColor",
8472
- strokeWidth: "2.5",
8473
- strokeLinecap: "round",
8474
- strokeLinejoin: "round",
8475
- children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M21 12a9 9 0 1 1-6.219-8.56", stroke: color || "currentColor", className: "text-accent1" })
8492
+ children: resolvedVariant === "pulse" ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
8493
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { className: "spinner-pulse-ring", cx: "12", cy: "12", r: "7" }),
8494
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { className: "spinner-pulse-core", cx: "12", cy: "12", r: "5" })
8495
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("circle", { className: "spinner-ring", cx: "12", cy: "12", r: "8.5" })
8476
8496
  }
8477
8497
  );
8478
8498
  }
8479
8499
 
8480
8500
  function MetricsCardLoading({ className }) {
8481
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex items-center justify-center", className), children: /* @__PURE__ */ jsxRuntime.jsx(Spinner, { size: "md", color: tokens.Colors.neutral1 }) });
8501
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex items-center justify-center", className), children: /* @__PURE__ */ jsxRuntime.jsx(Spinner, { size: "md", variant: "pulse", className: "text-neutral1" }) });
8482
8502
  }
8483
8503
 
8484
8504
  function MetricsCardNoData({ message = "No data yet", className }) {
@@ -8565,7 +8585,7 @@ function MetricsKpiCardLabel({ children, className }) {
8565
8585
  }
8566
8586
 
8567
8587
  function MetricsKpiCardLoading({ className }) {
8568
- return /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("text-sm", className), children: /* @__PURE__ */ jsxRuntime.jsx(Spinner, { size: "md", color: tokens.Colors.neutral1 }) });
8588
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("text-sm", className), children: /* @__PURE__ */ jsxRuntime.jsx(Spinner, { size: "md", variant: "pulse", className: "text-neutral1" }) });
8569
8589
  }
8570
8590
 
8571
8591
  function MetricsKpiCardNoChange({
@@ -8951,7 +8971,7 @@ function PickMultiPanel({ field, tokens, onChange }) {
8951
8971
  }
8952
8972
  ),
8953
8973
  field.isLoading ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 px-2 py-1.5 text-ui-sm text-neutral3", children: [
8954
- /* @__PURE__ */ jsxRuntime.jsx(Spinner, { size: "sm", className: "w-3 h-3", color: "var(--neutral3)" }),
8974
+ /* @__PURE__ */ jsxRuntime.jsx(Spinner, { size: "sm", className: "size-3 text-neutral3" }),
8955
8975
  "Loading options…"
8956
8976
  ] }) : filteredOptions.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-2 py-1.5 text-ui-sm text-neutral3", children: field.emptyText ?? "No option found." }) : field.multi ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-h-[80dvh] overflow-auto", children: filteredOptions.map((option) => {
8957
8977
  const checked = selectedValues.includes(option.value);
@@ -14611,6 +14631,22 @@ CardContent.displayName = "CardContent";
14611
14631
  const CardFooter = React__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("flex items-center p-4 pt-0", className), ...props }));
14612
14632
  CardFooter.displayName = "CardFooter";
14613
14633
 
14634
+ function DataPanelSectionHeading({ icon, className, children }) {
14635
+ return /* @__PURE__ */ jsxRuntime.jsxs(
14636
+ "div",
14637
+ {
14638
+ className: cn(
14639
+ "flex items-center gap-1.5 text-ui-sm uppercase tracking-widest text-neutral2 [&>svg]:size-3.5",
14640
+ className
14641
+ ),
14642
+ children: [
14643
+ icon,
14644
+ children
14645
+ ]
14646
+ }
14647
+ );
14648
+ }
14649
+
14614
14650
  const setSearchQuery = state.StateEffect.define();
14615
14651
  const searchHighlightMark = view.Decoration.mark({ class: "cm-search-match" });
14616
14652
  const searchHighlightField = state.StateField.define({
@@ -14801,19 +14837,7 @@ function DataCodeSection({
14801
14837
  if (!codeStr || codeStr === "null") return null;
14802
14838
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col gap-2", className), children: [
14803
14839
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
14804
- /* @__PURE__ */ jsxRuntime.jsxs(
14805
- "div",
14806
- {
14807
- className: cn(
14808
- "flex items-center gap-1.5 text-ui-sm uppercase tracking-widest text-neutral2",
14809
- "[&>svg]:size-3.5"
14810
- ),
14811
- children: [
14812
- icon,
14813
- title
14814
- ]
14815
- }
14816
- ),
14840
+ /* @__PURE__ */ jsxRuntime.jsx(DataPanelSectionHeading, { icon, children: title }),
14817
14841
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
14818
14842
  !usePlainTextView && /* @__PURE__ */ jsxRuntime.jsx(
14819
14843
  SearchFieldBlock,
@@ -15103,7 +15127,7 @@ const DataDetailsPanelKeyValueList = Object.assign(Root, {
15103
15127
 
15104
15128
  function DataDetailsPanelLoadingData({ children }) {
15105
15129
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-center gap-2 px-4 py-6 text-ui-sm text-neutral3", children: [
15106
- /* @__PURE__ */ jsxRuntime.jsx(Spinner, {}),
15130
+ /* @__PURE__ */ jsxRuntime.jsx(Spinner, { size: "sm", variant: "pulse", className: "text-neutral3" }),
15107
15131
  " ",
15108
15132
  children ?? "Loading..."
15109
15133
  ] });
@@ -15250,7 +15274,13 @@ function DataPanelHeader({ className, children }) {
15250
15274
  return /* @__PURE__ */ jsxRuntime.jsx(
15251
15275
  "div",
15252
15276
  {
15253
- className: cn("flex items-center justify-between gap-2 border-b border-border1 mx-4 py-3 min-h-14", className),
15277
+ className: cn(
15278
+ "flex items-center justify-between gap-2 mx-4 py-3 min-h-14",
15279
+ // Bottom border only when something follows the header (i.e. the panel is expanded).
15280
+ // When the panel is collapsed and the header is the only child, the border auto-hides.
15281
+ "not-last:border-b not-last:border-border1",
15282
+ className
15283
+ ),
15254
15284
  children
15255
15285
  }
15256
15286
  );
@@ -15262,7 +15292,7 @@ function DataPanelHeading({ className, children }) {
15262
15292
 
15263
15293
  function DataPanelLoadingData({ children }) {
15264
15294
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-center gap-2 px-4 py-6 text-ui-sm text-neutral2 min-h-32", children: [
15265
- /* @__PURE__ */ jsxRuntime.jsx(Spinner, { size: "sm", color: tokens.Colors.neutral1 }),
15295
+ /* @__PURE__ */ jsxRuntime.jsx(Spinner, { size: "sm", variant: "pulse", className: "text-neutral1" }),
15266
15296
  " ",
15267
15297
  children ?? "Loading..."
15268
15298
  ] });
@@ -15305,7 +15335,8 @@ const DataPanel = Object.assign(DataPanelRoot, {
15305
15335
  LoadingData: DataPanelLoadingData,
15306
15336
  NoData: DataPanelNoData,
15307
15337
  Content: DataPanelContent,
15308
- CodeSection: DataCodeSection
15338
+ CodeSection: DataCodeSection,
15339
+ SectionHeading: DataPanelSectionHeading
15309
15340
  });
15310
15341
 
15311
15342
  const DATE_PRESETS$1 = [
@@ -16092,6 +16123,22 @@ function is403ForbiddenError(error) {
16092
16123
  }
16093
16124
  return false;
16094
16125
  }
16126
+ function is404NotFoundError(error) {
16127
+ if (!error || typeof error !== "object") return false;
16128
+ if ("status" in error && error.status === 404) {
16129
+ return true;
16130
+ }
16131
+ if ("statusCode" in error && error.statusCode === 404) {
16132
+ return true;
16133
+ }
16134
+ if ("message" in error) {
16135
+ const message = error.message;
16136
+ if (typeof message === "string") {
16137
+ return /\bstatus:\s*404\b/.test(message);
16138
+ }
16139
+ }
16140
+ return false;
16141
+ }
16095
16142
  function isBranchesNotSupportedError(error) {
16096
16143
  if (!error || typeof error !== "object" || !("message" in error)) return false;
16097
16144
  const message = error.message;
@@ -20106,7 +20153,8 @@ function TraceDataPanelView({
20106
20153
  timelineChartWidth = "default",
20107
20154
  LinkComponent,
20108
20155
  traceHref,
20109
- anchorSpanId
20156
+ anchorSpanId,
20157
+ showUnavailableFeaturesMsg = true
20110
20158
  }) {
20111
20159
  const isOnTracePage = placement === "trace-page";
20112
20160
  const [internalCollapsed, setInternalCollapsed] = React.useState(false);
@@ -20171,7 +20219,7 @@ function TraceDataPanelView({
20171
20219
  children: collapsed ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronsUpDownIcon, {}) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronsDownUpIcon, {})
20172
20220
  }
20173
20221
  ),
20174
- /* @__PURE__ */ jsxRuntime.jsx(
20222
+ (onPrevious || onNext) && /* @__PURE__ */ jsxRuntime.jsx(
20175
20223
  DataPanel.NextPrevNav,
20176
20224
  {
20177
20225
  onPrevious,
@@ -20206,7 +20254,7 @@ function TraceDataPanelView({
20206
20254
  "Save as Dataset Item"
20207
20255
  ] })
20208
20256
  ] }),
20209
- !isOnTracePage && !onEvaluateTrace && !onSaveAsDatasetItem && /* @__PURE__ */ jsxRuntime.jsx(Notice, { variant: "info", className: "mb-6", children: /* @__PURE__ */ jsxRuntime.jsx(Notice.Message, { children: "Evaluating traces and saving them as dataset items is available in Mastra Studio (local or deployed)." }) }),
20257
+ !isOnTracePage && !onEvaluateTrace && !onSaveAsDatasetItem && showUnavailableFeaturesMsg && /* @__PURE__ */ jsxRuntime.jsx(Notice, { variant: "info", className: "mb-6", children: /* @__PURE__ */ jsxRuntime.jsx(Notice.Message, { children: "Evaluating traces and saving them as dataset items is available in Mastra Studio (local or deployed)." }) }),
20210
20258
  /* @__PURE__ */ jsxRuntime.jsx(
20211
20259
  TraceTimeline,
20212
20260
  {
@@ -22866,6 +22914,7 @@ exports.inputOutlineAndFocusStyle = inputOutlineAndFocusStyle;
22866
22914
  exports.inputSurfaceAndFocusStyle = inputSurfaceAndFocusStyle;
22867
22915
  exports.is401UnauthorizedError = is401UnauthorizedError;
22868
22916
  exports.is403ForbiddenError = is403ForbiddenError;
22917
+ exports.is404NotFoundError = is404NotFoundError;
22869
22918
  exports.isBranchesNotSupportedError = isBranchesNotSupportedError;
22870
22919
  exports.isNonRetryableError = isNonRetryableError;
22871
22920
  exports.isObjectEmpty = isObjectEmpty;