@mastra/playground-ui 48.0.0 → 48.1.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,28 @@
1
1
  # @mastra/playground-ui
2
2
 
3
+ ## 48.1.0-alpha.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Made the task list collapsible and moved its scrolling to the design system scroll area. ([#21337](https://github.com/mastra-ai/mastra/pull/21337))
8
+
9
+ Clicking the task list header now collapses it. The collapsed row keeps the completion count and shows the task currently in progress — or the next pending one — with its status icon and color, so the panel can be minimized without losing track of where the agent is. Long lists scroll inside `ScrollArea` (overlay scrollbar, edge fades) instead of a raw `overflow-y` container.
10
+
11
+ Use `defaultOpen` to render it collapsed:
12
+
13
+ ```tsx
14
+ <TaskList tasks={tasks} defaultOpen={false} />
15
+ ```
16
+
17
+ ### Patch Changes
18
+
19
+ - Fixed the composer edge glow so it follows the cursor only when the cursor is actually there. Focusing the composer used to light the moving arc as well, which meant the coloured segment kept sliding around the border while you typed or moved the mouse anywhere on the page. Focus now just brightens the border, and the arc lights on hover. ([#21320](https://github.com/mastra-ai/mastra/pull/21320))
20
+
21
+ - Updated dependencies [[`088e41e`](https://github.com/mastra-ai/mastra/commit/088e41e434ed05f2c674b254f1034ec46a57a7be), [`b2f0013`](https://github.com/mastra-ai/mastra/commit/b2f0013375588d40c03c13e843b99c0ff8872ca5), [`3b541ae`](https://github.com/mastra-ai/mastra/commit/3b541ae5d410c52b80a7e381d84d021cddb9a449), [`ae79e34`](https://github.com/mastra-ai/mastra/commit/ae79e34c0bd8674fc24c7524217bfc4a051c6136), [`a6c4399`](https://github.com/mastra-ai/mastra/commit/a6c4399763590b3dae21a2c81826e89a3b1deee4)]:
22
+ - @mastra/core@1.59.0-alpha.0
23
+ - @mastra/client-js@1.39.1-alpha.0
24
+ - @mastra/react@1.4.3-alpha.0
25
+
3
26
  ## 48.0.0
4
27
 
5
28
  ### Minor Changes
package/dist/Composer.css CHANGED
@@ -47,8 +47,8 @@
47
47
  background-color: var(--border2);
48
48
  }
49
49
 
50
- .composer-ring:hover,
51
- .composer-ring:focus-within {
50
+ /* The arc tracks the cursor, so it lights on hover only — focus brightens the edge instead. */
51
+ .composer-ring:hover {
52
52
  --composer-ring-strength: 0.4;
53
53
  }
54
54
 
@@ -5,11 +5,19 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
5
5
  const jsxRuntime = require('react/jsx-runtime');
6
6
  const lucideReact = require('lucide-react');
7
7
  const React = require('react');
8
+ const collapsible = require('../../collapsible-CoBU143c.cjs');
9
+ const scrollArea = require('../../scroll-area-Dv6QagXt.cjs');
8
10
  const utils_cn = require('../../cn-vA5sWo9W.cjs');
9
11
 
10
12
  const TaskListContainer = ({ className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx("section", { className: utils_cn.cn("rounded-2xl border border-border2/40 bg-surface3 px-3 py-2.5", className), ...props });
11
- const TaskListHeader = ({ className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx("header", { className: utils_cn.cn("mb-2 flex items-center gap-2", className), ...props });
12
- const TaskListCount = ({ completed, total, className, ...props }) => /* @__PURE__ */ jsxRuntime.jsxs("span", { className: utils_cn.cn("ml-auto text-ui-xs text-neutral4 tabular-nums", className), ...props, children: [
13
+ const TaskListHeader = ({ className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
14
+ collapsible.CollapsibleTrigger,
15
+ {
16
+ className: utils_cn.cn("flex w-full cursor-pointer items-center gap-2 text-left text-neutral4", className),
17
+ ...props
18
+ }
19
+ );
20
+ const TaskListCount = ({ completed, total, className, ...props }) => /* @__PURE__ */ jsxRuntime.jsxs("span", { className: utils_cn.cn("ml-auto shrink-0 text-ui-xs text-neutral4 tabular-nums", className), ...props, children: [
13
21
  completed,
14
22
  "/",
15
23
  total,
@@ -25,7 +33,7 @@ const TaskListProgress = ({ completed, total, className, ...props }) => {
25
33
  "aria-valuemin": 0,
26
34
  "aria-valuemax": total,
27
35
  "aria-valuenow": completed,
28
- className: utils_cn.cn("mb-2.5 h-1 w-full rounded-full bg-surface4", className),
36
+ className: utils_cn.cn("mt-2 mb-2.5 h-1 w-full rounded-full bg-surface4", className),
29
37
  ...props,
30
38
  children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-accent6 h-full rounded-full transition-all duration-300", style: { width: `${percentage}%` } })
31
39
  }
@@ -46,38 +54,56 @@ const textClasses = {
46
54
  in_progress: "font-medium text-warning1",
47
55
  pending: "text-neutral5"
48
56
  };
49
- const TaskListStatusIcon = ({ status, className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-label": statusLabels[status], className: utils_cn.cn("pt-0.5", className), ...props, children: icons[status] });
57
+ const taskLabel = (task) => task.status === "in_progress" ? task.activeForm : task.content;
58
+ const TaskListStatusIcon = ({ status, className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-label": statusLabels[status], className: utils_cn.cn("flex pt-0.5", className), ...props, children: icons[status] });
50
59
  const TaskListRow = ({ task, className, ...props }) => /* @__PURE__ */ jsxRuntime.jsxs("li", { className: utils_cn.cn("flex items-start gap-2 py-0.5", className), ...props, children: [
51
60
  /* @__PURE__ */ jsxRuntime.jsx(TaskListStatusIcon, { status: task.status }),
52
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: utils_cn.cn("text-ui-sm leading-ui-sm", textClasses[task.status]), children: task.status === "in_progress" ? task.activeForm : task.content })
61
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: utils_cn.cn("text-ui-sm leading-ui-sm", textClasses[task.status]), children: taskLabel(task) })
53
62
  ] });
63
+ const TaskListSummary = ({ task }) => /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex min-w-0 flex-1 items-center gap-2", children: [
64
+ /* @__PURE__ */ jsxRuntime.jsx(TaskListStatusIcon, { status: task.status, className: "pt-0" }),
65
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: utils_cn.cn("truncate text-ui-sm leading-ui-sm", textClasses[task.status]), children: taskLabel(task) })
66
+ ] });
67
+ const TaskListTitle = ({ title }) => /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex min-w-0 flex-1 items-center gap-2", children: [
68
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ListChecks, { className: "text-accent6 size-4 shrink-0" }),
69
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-sm leading-ui-sm text-neutral6 truncate font-medium", children: title })
70
+ ] });
71
+ const scrollTaskIntoView = (node) => {
72
+ if (typeof node?.scrollIntoView === "function") node.scrollIntoView({ block: "nearest" });
73
+ };
54
74
  const TaskList = ({
55
75
  tasks,
56
76
  title = "Tasks",
57
77
  hideWhenEmpty = true,
58
78
  hideWhenComplete = true,
59
79
  scrollActiveIntoView = true,
80
+ defaultOpen = true,
60
81
  ...props
61
82
  }) => {
62
- const activeTaskRef = React.useRef(null);
63
- const activeTaskId = tasks.find((task) => task.status === "in_progress")?.id;
83
+ const [open, setOpen] = React.useState(defaultOpen);
84
+ const activeTask = tasks.find((task) => task.status === "in_progress");
85
+ const summaryTask = activeTask ?? tasks.find((task) => task.status === "pending");
64
86
  const completed = tasks.filter((task) => task.status === "completed").length;
65
87
  const total = tasks.length;
66
- React.useEffect(() => {
67
- if (!scrollActiveIntoView || !activeTaskRef.current || typeof activeTaskRef.current.scrollIntoView !== "function")
68
- return;
69
- activeTaskRef.current.scrollIntoView({ block: "nearest" });
70
- }, [activeTaskId, scrollActiveIntoView]);
71
88
  if (hideWhenEmpty && total === 0 || hideWhenComplete && total > 0 && completed === total) return null;
72
- return /* @__PURE__ */ jsxRuntime.jsxs(TaskListContainer, { "aria-label": "Task list", "data-testid": "task-list", ...props, children: [
89
+ return /* @__PURE__ */ jsxRuntime.jsx(TaskListContainer, { "aria-label": "Task list", "data-testid": "task-list", ...props, children: /* @__PURE__ */ jsxRuntime.jsxs(collapsible.Collapsible, { open, onOpenChange: setOpen, children: [
73
90
  /* @__PURE__ */ jsxRuntime.jsxs(TaskListHeader, { children: [
74
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ListChecks, { className: "text-accent6 size-4 shrink-0" }),
75
- /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-ui-sm leading-ui-sm text-neutral6 font-medium", children: title }),
91
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { className: "size-3.5 shrink-0" }),
92
+ open || !summaryTask ? /* @__PURE__ */ jsxRuntime.jsx(TaskListTitle, { title }) : /* @__PURE__ */ jsxRuntime.jsx(TaskListSummary, { task: summaryTask }),
76
93
  /* @__PURE__ */ jsxRuntime.jsx(TaskListCount, { completed, total })
77
94
  ] }),
78
- /* @__PURE__ */ jsxRuntime.jsx(TaskListProgress, { completed, total }),
79
- /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "max-h-32 space-y-1 overflow-y-auto pr-1", children: tasks.map((task) => /* @__PURE__ */ jsxRuntime.jsx(TaskListRow, { ref: task.id === activeTaskId ? activeTaskRef : void 0, task }, task.id)) })
80
- ] });
95
+ /* @__PURE__ */ jsxRuntime.jsxs(collapsible.CollapsibleContent, { children: [
96
+ /* @__PURE__ */ jsxRuntime.jsx(TaskListProgress, { completed, total }),
97
+ /* @__PURE__ */ jsxRuntime.jsx(scrollArea.ScrollArea, { maxHeight: "8rem", viewPortClassName: "pr-1", children: /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "space-y-1", children: tasks.map((task) => /* @__PURE__ */ jsxRuntime.jsx(
98
+ TaskListRow,
99
+ {
100
+ ref: scrollActiveIntoView && task.id === activeTask?.id ? scrollTaskIntoView : void 0,
101
+ task
102
+ },
103
+ task.id
104
+ )) }) })
105
+ ] })
106
+ ] }) });
81
107
  };
82
108
 
83
109
  exports.TaskList = TaskList;
@@ -1 +1 @@
1
- {"version":3,"file":"task-list.cjs.js","sources":["../../../src/ds/components/ai/task-list/task-list.tsx"],"sourcesContent":["import type { TaskItem } from '@mastra/core/signals';\nimport { CheckCircle2, Circle, ListChecks, Loader2 } from 'lucide-react';\nimport { useEffect, useRef } from 'react';\nimport type { ComponentProps, ReactNode } from 'react';\nimport { cn } from '@/lib/utils';\n\nexport type TaskListItem = TaskItem;\n\nexport const TaskListContainer = ({ className, ...props }: ComponentProps<'section'>) => (\n <section className={cn('rounded-2xl border border-border2/40 bg-surface3 px-3 py-2.5', className)} {...props} />\n);\n\nexport const TaskListHeader = ({ className, ...props }: ComponentProps<'header'>) => (\n <header className={cn('mb-2 flex items-center gap-2', className)} {...props} />\n);\n\nexport interface TaskListCountProps extends ComponentProps<'span'> {\n completed: number;\n total: number;\n}\n\nexport const TaskListCount = ({ completed, total, className, ...props }: TaskListCountProps) => (\n <span className={cn('ml-auto text-ui-xs text-neutral4 tabular-nums', className)} {...props}>\n {completed}/{total} completed\n </span>\n);\n\nexport interface TaskListProgressProps extends Omit<ComponentProps<'div'>, 'children'> {\n completed: number;\n total: number;\n}\n\nexport const TaskListProgress = ({ completed, total, className, ...props }: TaskListProgressProps) => {\n const percentage = total === 0 ? 0 : (completed / total) * 100;\n return (\n <div\n role=\"progressbar\"\n aria-label=\"Task completion\"\n aria-valuemin={0}\n aria-valuemax={total}\n aria-valuenow={completed}\n className={cn('mb-2.5 h-1 w-full rounded-full bg-surface4', className)}\n {...props}\n >\n <div className=\"bg-accent6 h-full rounded-full transition-all duration-300\" style={{ width: `${percentage}%` }} />\n </div>\n );\n};\n\nconst icons: Record<TaskListItem['status'], ReactNode> = {\n completed: <CheckCircle2 className=\"text-positive1 size-3.5 shrink-0\" />,\n in_progress: <Loader2 className=\"text-warning1 size-3.5 shrink-0 motion-safe:animate-spin\" />,\n pending: <Circle className=\"text-neutral4 size-3.5 shrink-0\" />,\n};\n\nconst statusLabels: Record<TaskListItem['status'], string> = {\n completed: 'Completed',\n in_progress: 'In progress',\n pending: 'Pending',\n};\n\nconst textClasses: Record<TaskListItem['status'], string> = {\n completed: 'text-neutral4 line-through',\n in_progress: 'font-medium text-warning1',\n pending: 'text-neutral5',\n};\n\nexport interface TaskListStatusIconProps extends ComponentProps<'span'> {\n status: TaskListItem['status'];\n}\n\nexport const TaskListStatusIcon = ({ status, className, ...props }: TaskListStatusIconProps) => (\n <span aria-label={statusLabels[status]} className={cn('pt-0.5', className)} {...props}>\n {icons[status]}\n </span>\n);\n\nexport interface TaskListRowProps extends ComponentProps<'li'> {\n task: TaskListItem;\n}\n\nexport const TaskListRow = ({ task, className, ...props }: TaskListRowProps) => (\n <li className={cn('flex items-start gap-2 py-0.5', className)} {...props}>\n <TaskListStatusIcon status={task.status} />\n <span className={cn('text-ui-sm leading-ui-sm', textClasses[task.status])}>\n {task.status === 'in_progress' ? task.activeForm : task.content}\n </span>\n </li>\n);\n\nexport interface TaskListProps extends Omit<ComponentProps<typeof TaskListContainer>, 'children' | 'title'> {\n tasks: TaskListItem[];\n title?: ReactNode;\n hideWhenEmpty?: boolean;\n hideWhenComplete?: boolean;\n scrollActiveIntoView?: boolean;\n}\n\nexport const TaskList = ({\n tasks,\n title = 'Tasks',\n hideWhenEmpty = true,\n hideWhenComplete = true,\n scrollActiveIntoView = true,\n ...props\n}: TaskListProps) => {\n const activeTaskRef = useRef<HTMLLIElement | null>(null);\n const activeTaskId = tasks.find(task => task.status === 'in_progress')?.id;\n const completed = tasks.filter(task => task.status === 'completed').length;\n const total = tasks.length;\n\n useEffect(() => {\n if (!scrollActiveIntoView || !activeTaskRef.current || typeof activeTaskRef.current.scrollIntoView !== 'function')\n return;\n activeTaskRef.current.scrollIntoView({ block: 'nearest' });\n }, [activeTaskId, scrollActiveIntoView]);\n\n if ((hideWhenEmpty && total === 0) || (hideWhenComplete && total > 0 && completed === total)) return null;\n\n return (\n <TaskListContainer aria-label=\"Task list\" data-testid=\"task-list\" {...props}>\n <TaskListHeader>\n <ListChecks className=\"text-accent6 size-4 shrink-0\" />\n <h2 className=\"text-ui-sm leading-ui-sm text-neutral6 font-medium\">{title}</h2>\n <TaskListCount completed={completed} total={total} />\n </TaskListHeader>\n <TaskListProgress completed={completed} total={total} />\n <ul className=\"max-h-32 space-y-1 overflow-y-auto pr-1\">\n {tasks.map(task => (\n <TaskListRow key={task.id} ref={task.id === activeTaskId ? activeTaskRef : undefined} task={task} />\n ))}\n </ul>\n </TaskListContainer>\n );\n};\n"],"names":["jsx","cn","jsxs","CheckCircle2","Loader2","Circle","useRef","useEffect","ListChecks"],"mappings":"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"}
1
+ {"version":3,"file":"task-list.cjs.js","sources":["../../../src/ds/components/ai/task-list/task-list.tsx"],"sourcesContent":["import type { TaskItem } from '@mastra/core/signals';\nimport { CheckCircle2, ChevronRight, Circle, ListChecks, Loader2 } from 'lucide-react';\nimport { useState } from 'react';\nimport type { ComponentProps, ReactNode } from 'react';\nimport { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/ds/components/Collapsible';\nimport { ScrollArea } from '@/ds/components/ScrollArea';\nimport { cn } from '@/lib/utils';\n\nexport type TaskListItem = TaskItem;\n\nexport const TaskListContainer = ({ className, ...props }: ComponentProps<'section'>) => (\n <section className={cn('rounded-2xl border border-border2/40 bg-surface3 px-3 py-2.5', className)} {...props} />\n);\n\nexport const TaskListHeader = ({ className, ...props }: ComponentProps<typeof CollapsibleTrigger>) => (\n <CollapsibleTrigger\n className={cn('flex w-full cursor-pointer items-center gap-2 text-left text-neutral4', className)}\n {...props}\n />\n);\n\nexport interface TaskListCountProps extends ComponentProps<'span'> {\n completed: number;\n total: number;\n}\n\nexport const TaskListCount = ({ completed, total, className, ...props }: TaskListCountProps) => (\n <span className={cn('ml-auto shrink-0 text-ui-xs text-neutral4 tabular-nums', className)} {...props}>\n {completed}/{total} completed\n </span>\n);\n\nexport interface TaskListProgressProps extends Omit<ComponentProps<'div'>, 'children'> {\n completed: number;\n total: number;\n}\n\nexport const TaskListProgress = ({ completed, total, className, ...props }: TaskListProgressProps) => {\n const percentage = total === 0 ? 0 : (completed / total) * 100;\n return (\n <div\n role=\"progressbar\"\n aria-label=\"Task completion\"\n aria-valuemin={0}\n aria-valuemax={total}\n aria-valuenow={completed}\n className={cn('mt-2 mb-2.5 h-1 w-full rounded-full bg-surface4', className)}\n {...props}\n >\n <div className=\"bg-accent6 h-full rounded-full transition-all duration-300\" style={{ width: `${percentage}%` }} />\n </div>\n );\n};\n\nconst icons: Record<TaskListItem['status'], ReactNode> = {\n completed: <CheckCircle2 className=\"text-positive1 size-3.5 shrink-0\" />,\n in_progress: <Loader2 className=\"text-warning1 size-3.5 shrink-0 motion-safe:animate-spin\" />,\n pending: <Circle className=\"text-neutral4 size-3.5 shrink-0\" />,\n};\n\nconst statusLabels: Record<TaskListItem['status'], string> = {\n completed: 'Completed',\n in_progress: 'In progress',\n pending: 'Pending',\n};\n\nconst textClasses: Record<TaskListItem['status'], string> = {\n completed: 'text-neutral4 line-through',\n in_progress: 'font-medium text-warning1',\n pending: 'text-neutral5',\n};\n\nconst taskLabel = (task: TaskListItem) => (task.status === 'in_progress' ? task.activeForm : task.content);\n\nexport interface TaskListStatusIconProps extends ComponentProps<'span'> {\n status: TaskListItem['status'];\n}\n\nexport const TaskListStatusIcon = ({ status, className, ...props }: TaskListStatusIconProps) => (\n <span aria-label={statusLabels[status]} className={cn('flex pt-0.5', className)} {...props}>\n {icons[status]}\n </span>\n);\n\nexport interface TaskListRowProps extends ComponentProps<'li'> {\n task: TaskListItem;\n}\n\nexport const TaskListRow = ({ task, className, ...props }: TaskListRowProps) => (\n <li className={cn('flex items-start gap-2 py-0.5', className)} {...props}>\n <TaskListStatusIcon status={task.status} />\n <span className={cn('text-ui-sm leading-ui-sm', textClasses[task.status])}>{taskLabel(task)}</span>\n </li>\n);\n\nconst TaskListSummary = ({ task }: { task: TaskListItem }) => (\n <span className=\"flex min-w-0 flex-1 items-center gap-2\">\n <TaskListStatusIcon status={task.status} className=\"pt-0\" />\n <span className={cn('truncate text-ui-sm leading-ui-sm', textClasses[task.status])}>{taskLabel(task)}</span>\n </span>\n);\n\nconst TaskListTitle = ({ title }: { title: ReactNode }) => (\n <span className=\"flex min-w-0 flex-1 items-center gap-2\">\n <ListChecks className=\"text-accent6 size-4 shrink-0\" />\n <span className=\"text-ui-sm leading-ui-sm text-neutral6 truncate font-medium\">{title}</span>\n </span>\n);\n\nconst scrollTaskIntoView = (node: HTMLLIElement | null) => {\n if (typeof node?.scrollIntoView === 'function') node.scrollIntoView({ block: 'nearest' });\n};\n\nexport interface TaskListProps extends Omit<ComponentProps<typeof TaskListContainer>, 'children' | 'title'> {\n tasks: TaskListItem[];\n title?: ReactNode;\n hideWhenEmpty?: boolean;\n hideWhenComplete?: boolean;\n scrollActiveIntoView?: boolean;\n defaultOpen?: boolean;\n}\n\nexport const TaskList = ({\n tasks,\n title = 'Tasks',\n hideWhenEmpty = true,\n hideWhenComplete = true,\n scrollActiveIntoView = true,\n defaultOpen = true,\n ...props\n}: TaskListProps) => {\n const [open, setOpen] = useState(defaultOpen);\n const activeTask = tasks.find(task => task.status === 'in_progress');\n const summaryTask = activeTask ?? tasks.find(task => task.status === 'pending');\n const completed = tasks.filter(task => task.status === 'completed').length;\n const total = tasks.length;\n\n if ((hideWhenEmpty && total === 0) || (hideWhenComplete && total > 0 && completed === total)) return null;\n\n return (\n <TaskListContainer aria-label=\"Task list\" data-testid=\"task-list\" {...props}>\n <Collapsible open={open} onOpenChange={setOpen}>\n <TaskListHeader>\n <ChevronRight className=\"size-3.5 shrink-0\" />\n {open || !summaryTask ? <TaskListTitle title={title} /> : <TaskListSummary task={summaryTask} />}\n <TaskListCount completed={completed} total={total} />\n </TaskListHeader>\n <CollapsibleContent>\n <TaskListProgress completed={completed} total={total} />\n <ScrollArea maxHeight=\"8rem\" viewPortClassName=\"pr-1\">\n <ul className=\"space-y-1\">\n {tasks.map(task => (\n <TaskListRow\n key={task.id}\n ref={scrollActiveIntoView && task.id === activeTask?.id ? scrollTaskIntoView : undefined}\n task={task}\n />\n ))}\n </ul>\n </ScrollArea>\n </CollapsibleContent>\n </Collapsible>\n </TaskListContainer>\n );\n};\n"],"names":["jsx","cn","CollapsibleTrigger","jsxs","CheckCircle2","Loader2","Circle","ListChecks","useState","Collapsible","ChevronRight","CollapsibleContent","ScrollArea"],"mappings":"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"}
@@ -1,11 +1,19 @@
1
- import { jsxs, jsx } from 'react/jsx-runtime';
2
- import { ListChecks, Circle, Loader2, CheckCircle2 } from 'lucide-react';
3
- import { useRef, useEffect } from 'react';
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import { ChevronRight, ListChecks, Circle, Loader2, CheckCircle2 } from 'lucide-react';
3
+ import { useState } from 'react';
4
+ import { C as Collapsible, a as CollapsibleContent, b as CollapsibleTrigger } from '../../collapsible-D6MHpP1g.js';
5
+ import { S as ScrollArea } from '../../scroll-area-DZrEuKjC.js';
4
6
  import { c as cn } from '../../cn-BakJzhuv.js';
5
7
 
6
8
  const TaskListContainer = ({ className, ...props }) => /* @__PURE__ */ jsx("section", { className: cn("rounded-2xl border border-border2/40 bg-surface3 px-3 py-2.5", className), ...props });
7
- const TaskListHeader = ({ className, ...props }) => /* @__PURE__ */ jsx("header", { className: cn("mb-2 flex items-center gap-2", className), ...props });
8
- const TaskListCount = ({ completed, total, className, ...props }) => /* @__PURE__ */ jsxs("span", { className: cn("ml-auto text-ui-xs text-neutral4 tabular-nums", className), ...props, children: [
9
+ const TaskListHeader = ({ className, ...props }) => /* @__PURE__ */ jsx(
10
+ CollapsibleTrigger,
11
+ {
12
+ className: cn("flex w-full cursor-pointer items-center gap-2 text-left text-neutral4", className),
13
+ ...props
14
+ }
15
+ );
16
+ const TaskListCount = ({ completed, total, className, ...props }) => /* @__PURE__ */ jsxs("span", { className: cn("ml-auto shrink-0 text-ui-xs text-neutral4 tabular-nums", className), ...props, children: [
9
17
  completed,
10
18
  "/",
11
19
  total,
@@ -21,7 +29,7 @@ const TaskListProgress = ({ completed, total, className, ...props }) => {
21
29
  "aria-valuemin": 0,
22
30
  "aria-valuemax": total,
23
31
  "aria-valuenow": completed,
24
- className: cn("mb-2.5 h-1 w-full rounded-full bg-surface4", className),
32
+ className: cn("mt-2 mb-2.5 h-1 w-full rounded-full bg-surface4", className),
25
33
  ...props,
26
34
  children: /* @__PURE__ */ jsx("div", { className: "bg-accent6 h-full rounded-full transition-all duration-300", style: { width: `${percentage}%` } })
27
35
  }
@@ -42,38 +50,56 @@ const textClasses = {
42
50
  in_progress: "font-medium text-warning1",
43
51
  pending: "text-neutral5"
44
52
  };
45
- const TaskListStatusIcon = ({ status, className, ...props }) => /* @__PURE__ */ jsx("span", { "aria-label": statusLabels[status], className: cn("pt-0.5", className), ...props, children: icons[status] });
53
+ const taskLabel = (task) => task.status === "in_progress" ? task.activeForm : task.content;
54
+ const TaskListStatusIcon = ({ status, className, ...props }) => /* @__PURE__ */ jsx("span", { "aria-label": statusLabels[status], className: cn("flex pt-0.5", className), ...props, children: icons[status] });
46
55
  const TaskListRow = ({ task, className, ...props }) => /* @__PURE__ */ jsxs("li", { className: cn("flex items-start gap-2 py-0.5", className), ...props, children: [
47
56
  /* @__PURE__ */ jsx(TaskListStatusIcon, { status: task.status }),
48
- /* @__PURE__ */ jsx("span", { className: cn("text-ui-sm leading-ui-sm", textClasses[task.status]), children: task.status === "in_progress" ? task.activeForm : task.content })
57
+ /* @__PURE__ */ jsx("span", { className: cn("text-ui-sm leading-ui-sm", textClasses[task.status]), children: taskLabel(task) })
49
58
  ] });
59
+ const TaskListSummary = ({ task }) => /* @__PURE__ */ jsxs("span", { className: "flex min-w-0 flex-1 items-center gap-2", children: [
60
+ /* @__PURE__ */ jsx(TaskListStatusIcon, { status: task.status, className: "pt-0" }),
61
+ /* @__PURE__ */ jsx("span", { className: cn("truncate text-ui-sm leading-ui-sm", textClasses[task.status]), children: taskLabel(task) })
62
+ ] });
63
+ const TaskListTitle = ({ title }) => /* @__PURE__ */ jsxs("span", { className: "flex min-w-0 flex-1 items-center gap-2", children: [
64
+ /* @__PURE__ */ jsx(ListChecks, { className: "text-accent6 size-4 shrink-0" }),
65
+ /* @__PURE__ */ jsx("span", { className: "text-ui-sm leading-ui-sm text-neutral6 truncate font-medium", children: title })
66
+ ] });
67
+ const scrollTaskIntoView = (node) => {
68
+ if (typeof node?.scrollIntoView === "function") node.scrollIntoView({ block: "nearest" });
69
+ };
50
70
  const TaskList = ({
51
71
  tasks,
52
72
  title = "Tasks",
53
73
  hideWhenEmpty = true,
54
74
  hideWhenComplete = true,
55
75
  scrollActiveIntoView = true,
76
+ defaultOpen = true,
56
77
  ...props
57
78
  }) => {
58
- const activeTaskRef = useRef(null);
59
- const activeTaskId = tasks.find((task) => task.status === "in_progress")?.id;
79
+ const [open, setOpen] = useState(defaultOpen);
80
+ const activeTask = tasks.find((task) => task.status === "in_progress");
81
+ const summaryTask = activeTask ?? tasks.find((task) => task.status === "pending");
60
82
  const completed = tasks.filter((task) => task.status === "completed").length;
61
83
  const total = tasks.length;
62
- useEffect(() => {
63
- if (!scrollActiveIntoView || !activeTaskRef.current || typeof activeTaskRef.current.scrollIntoView !== "function")
64
- return;
65
- activeTaskRef.current.scrollIntoView({ block: "nearest" });
66
- }, [activeTaskId, scrollActiveIntoView]);
67
84
  if (hideWhenEmpty && total === 0 || hideWhenComplete && total > 0 && completed === total) return null;
68
- return /* @__PURE__ */ jsxs(TaskListContainer, { "aria-label": "Task list", "data-testid": "task-list", ...props, children: [
85
+ return /* @__PURE__ */ jsx(TaskListContainer, { "aria-label": "Task list", "data-testid": "task-list", ...props, children: /* @__PURE__ */ jsxs(Collapsible, { open, onOpenChange: setOpen, children: [
69
86
  /* @__PURE__ */ jsxs(TaskListHeader, { children: [
70
- /* @__PURE__ */ jsx(ListChecks, { className: "text-accent6 size-4 shrink-0" }),
71
- /* @__PURE__ */ jsx("h2", { className: "text-ui-sm leading-ui-sm text-neutral6 font-medium", children: title }),
87
+ /* @__PURE__ */ jsx(ChevronRight, { className: "size-3.5 shrink-0" }),
88
+ open || !summaryTask ? /* @__PURE__ */ jsx(TaskListTitle, { title }) : /* @__PURE__ */ jsx(TaskListSummary, { task: summaryTask }),
72
89
  /* @__PURE__ */ jsx(TaskListCount, { completed, total })
73
90
  ] }),
74
- /* @__PURE__ */ jsx(TaskListProgress, { completed, total }),
75
- /* @__PURE__ */ jsx("ul", { className: "max-h-32 space-y-1 overflow-y-auto pr-1", children: tasks.map((task) => /* @__PURE__ */ jsx(TaskListRow, { ref: task.id === activeTaskId ? activeTaskRef : void 0, task }, task.id)) })
76
- ] });
91
+ /* @__PURE__ */ jsxs(CollapsibleContent, { children: [
92
+ /* @__PURE__ */ jsx(TaskListProgress, { completed, total }),
93
+ /* @__PURE__ */ jsx(ScrollArea, { maxHeight: "8rem", viewPortClassName: "pr-1", children: /* @__PURE__ */ jsx("ul", { className: "space-y-1", children: tasks.map((task) => /* @__PURE__ */ jsx(
94
+ TaskListRow,
95
+ {
96
+ ref: scrollActiveIntoView && task.id === activeTask?.id ? scrollTaskIntoView : void 0,
97
+ task
98
+ },
99
+ task.id
100
+ )) }) })
101
+ ] })
102
+ ] }) });
77
103
  };
78
104
 
79
105
  export { TaskList, TaskListContainer, TaskListCount, TaskListHeader, TaskListProgress, TaskListRow, TaskListStatusIcon };
@@ -1 +1 @@
1
- {"version":3,"file":"task-list.es.js","sources":["../../../src/ds/components/ai/task-list/task-list.tsx"],"sourcesContent":["import type { TaskItem } from '@mastra/core/signals';\nimport { CheckCircle2, Circle, ListChecks, Loader2 } from 'lucide-react';\nimport { useEffect, useRef } from 'react';\nimport type { ComponentProps, ReactNode } from 'react';\nimport { cn } from '@/lib/utils';\n\nexport type TaskListItem = TaskItem;\n\nexport const TaskListContainer = ({ className, ...props }: ComponentProps<'section'>) => (\n <section className={cn('rounded-2xl border border-border2/40 bg-surface3 px-3 py-2.5', className)} {...props} />\n);\n\nexport const TaskListHeader = ({ className, ...props }: ComponentProps<'header'>) => (\n <header className={cn('mb-2 flex items-center gap-2', className)} {...props} />\n);\n\nexport interface TaskListCountProps extends ComponentProps<'span'> {\n completed: number;\n total: number;\n}\n\nexport const TaskListCount = ({ completed, total, className, ...props }: TaskListCountProps) => (\n <span className={cn('ml-auto text-ui-xs text-neutral4 tabular-nums', className)} {...props}>\n {completed}/{total} completed\n </span>\n);\n\nexport interface TaskListProgressProps extends Omit<ComponentProps<'div'>, 'children'> {\n completed: number;\n total: number;\n}\n\nexport const TaskListProgress = ({ completed, total, className, ...props }: TaskListProgressProps) => {\n const percentage = total === 0 ? 0 : (completed / total) * 100;\n return (\n <div\n role=\"progressbar\"\n aria-label=\"Task completion\"\n aria-valuemin={0}\n aria-valuemax={total}\n aria-valuenow={completed}\n className={cn('mb-2.5 h-1 w-full rounded-full bg-surface4', className)}\n {...props}\n >\n <div className=\"bg-accent6 h-full rounded-full transition-all duration-300\" style={{ width: `${percentage}%` }} />\n </div>\n );\n};\n\nconst icons: Record<TaskListItem['status'], ReactNode> = {\n completed: <CheckCircle2 className=\"text-positive1 size-3.5 shrink-0\" />,\n in_progress: <Loader2 className=\"text-warning1 size-3.5 shrink-0 motion-safe:animate-spin\" />,\n pending: <Circle className=\"text-neutral4 size-3.5 shrink-0\" />,\n};\n\nconst statusLabels: Record<TaskListItem['status'], string> = {\n completed: 'Completed',\n in_progress: 'In progress',\n pending: 'Pending',\n};\n\nconst textClasses: Record<TaskListItem['status'], string> = {\n completed: 'text-neutral4 line-through',\n in_progress: 'font-medium text-warning1',\n pending: 'text-neutral5',\n};\n\nexport interface TaskListStatusIconProps extends ComponentProps<'span'> {\n status: TaskListItem['status'];\n}\n\nexport const TaskListStatusIcon = ({ status, className, ...props }: TaskListStatusIconProps) => (\n <span aria-label={statusLabels[status]} className={cn('pt-0.5', className)} {...props}>\n {icons[status]}\n </span>\n);\n\nexport interface TaskListRowProps extends ComponentProps<'li'> {\n task: TaskListItem;\n}\n\nexport const TaskListRow = ({ task, className, ...props }: TaskListRowProps) => (\n <li className={cn('flex items-start gap-2 py-0.5', className)} {...props}>\n <TaskListStatusIcon status={task.status} />\n <span className={cn('text-ui-sm leading-ui-sm', textClasses[task.status])}>\n {task.status === 'in_progress' ? task.activeForm : task.content}\n </span>\n </li>\n);\n\nexport interface TaskListProps extends Omit<ComponentProps<typeof TaskListContainer>, 'children' | 'title'> {\n tasks: TaskListItem[];\n title?: ReactNode;\n hideWhenEmpty?: boolean;\n hideWhenComplete?: boolean;\n scrollActiveIntoView?: boolean;\n}\n\nexport const TaskList = ({\n tasks,\n title = 'Tasks',\n hideWhenEmpty = true,\n hideWhenComplete = true,\n scrollActiveIntoView = true,\n ...props\n}: TaskListProps) => {\n const activeTaskRef = useRef<HTMLLIElement | null>(null);\n const activeTaskId = tasks.find(task => task.status === 'in_progress')?.id;\n const completed = tasks.filter(task => task.status === 'completed').length;\n const total = tasks.length;\n\n useEffect(() => {\n if (!scrollActiveIntoView || !activeTaskRef.current || typeof activeTaskRef.current.scrollIntoView !== 'function')\n return;\n activeTaskRef.current.scrollIntoView({ block: 'nearest' });\n }, [activeTaskId, scrollActiveIntoView]);\n\n if ((hideWhenEmpty && total === 0) || (hideWhenComplete && total > 0 && completed === total)) return null;\n\n return (\n <TaskListContainer aria-label=\"Task list\" data-testid=\"task-list\" {...props}>\n <TaskListHeader>\n <ListChecks className=\"text-accent6 size-4 shrink-0\" />\n <h2 className=\"text-ui-sm leading-ui-sm text-neutral6 font-medium\">{title}</h2>\n <TaskListCount completed={completed} total={total} />\n </TaskListHeader>\n <TaskListProgress completed={completed} total={total} />\n <ul className=\"max-h-32 space-y-1 overflow-y-auto pr-1\">\n {tasks.map(task => (\n <TaskListRow key={task.id} ref={task.id === activeTaskId ? activeTaskRef : undefined} task={task} />\n ))}\n </ul>\n </TaskListContainer>\n );\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"task-list.es.js","sources":["../../../src/ds/components/ai/task-list/task-list.tsx"],"sourcesContent":["import type { TaskItem } from '@mastra/core/signals';\nimport { CheckCircle2, ChevronRight, Circle, ListChecks, Loader2 } from 'lucide-react';\nimport { useState } from 'react';\nimport type { ComponentProps, ReactNode } from 'react';\nimport { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/ds/components/Collapsible';\nimport { ScrollArea } from '@/ds/components/ScrollArea';\nimport { cn } from '@/lib/utils';\n\nexport type TaskListItem = TaskItem;\n\nexport const TaskListContainer = ({ className, ...props }: ComponentProps<'section'>) => (\n <section className={cn('rounded-2xl border border-border2/40 bg-surface3 px-3 py-2.5', className)} {...props} />\n);\n\nexport const TaskListHeader = ({ className, ...props }: ComponentProps<typeof CollapsibleTrigger>) => (\n <CollapsibleTrigger\n className={cn('flex w-full cursor-pointer items-center gap-2 text-left text-neutral4', className)}\n {...props}\n />\n);\n\nexport interface TaskListCountProps extends ComponentProps<'span'> {\n completed: number;\n total: number;\n}\n\nexport const TaskListCount = ({ completed, total, className, ...props }: TaskListCountProps) => (\n <span className={cn('ml-auto shrink-0 text-ui-xs text-neutral4 tabular-nums', className)} {...props}>\n {completed}/{total} completed\n </span>\n);\n\nexport interface TaskListProgressProps extends Omit<ComponentProps<'div'>, 'children'> {\n completed: number;\n total: number;\n}\n\nexport const TaskListProgress = ({ completed, total, className, ...props }: TaskListProgressProps) => {\n const percentage = total === 0 ? 0 : (completed / total) * 100;\n return (\n <div\n role=\"progressbar\"\n aria-label=\"Task completion\"\n aria-valuemin={0}\n aria-valuemax={total}\n aria-valuenow={completed}\n className={cn('mt-2 mb-2.5 h-1 w-full rounded-full bg-surface4', className)}\n {...props}\n >\n <div className=\"bg-accent6 h-full rounded-full transition-all duration-300\" style={{ width: `${percentage}%` }} />\n </div>\n );\n};\n\nconst icons: Record<TaskListItem['status'], ReactNode> = {\n completed: <CheckCircle2 className=\"text-positive1 size-3.5 shrink-0\" />,\n in_progress: <Loader2 className=\"text-warning1 size-3.5 shrink-0 motion-safe:animate-spin\" />,\n pending: <Circle className=\"text-neutral4 size-3.5 shrink-0\" />,\n};\n\nconst statusLabels: Record<TaskListItem['status'], string> = {\n completed: 'Completed',\n in_progress: 'In progress',\n pending: 'Pending',\n};\n\nconst textClasses: Record<TaskListItem['status'], string> = {\n completed: 'text-neutral4 line-through',\n in_progress: 'font-medium text-warning1',\n pending: 'text-neutral5',\n};\n\nconst taskLabel = (task: TaskListItem) => (task.status === 'in_progress' ? task.activeForm : task.content);\n\nexport interface TaskListStatusIconProps extends ComponentProps<'span'> {\n status: TaskListItem['status'];\n}\n\nexport const TaskListStatusIcon = ({ status, className, ...props }: TaskListStatusIconProps) => (\n <span aria-label={statusLabels[status]} className={cn('flex pt-0.5', className)} {...props}>\n {icons[status]}\n </span>\n);\n\nexport interface TaskListRowProps extends ComponentProps<'li'> {\n task: TaskListItem;\n}\n\nexport const TaskListRow = ({ task, className, ...props }: TaskListRowProps) => (\n <li className={cn('flex items-start gap-2 py-0.5', className)} {...props}>\n <TaskListStatusIcon status={task.status} />\n <span className={cn('text-ui-sm leading-ui-sm', textClasses[task.status])}>{taskLabel(task)}</span>\n </li>\n);\n\nconst TaskListSummary = ({ task }: { task: TaskListItem }) => (\n <span className=\"flex min-w-0 flex-1 items-center gap-2\">\n <TaskListStatusIcon status={task.status} className=\"pt-0\" />\n <span className={cn('truncate text-ui-sm leading-ui-sm', textClasses[task.status])}>{taskLabel(task)}</span>\n </span>\n);\n\nconst TaskListTitle = ({ title }: { title: ReactNode }) => (\n <span className=\"flex min-w-0 flex-1 items-center gap-2\">\n <ListChecks className=\"text-accent6 size-4 shrink-0\" />\n <span className=\"text-ui-sm leading-ui-sm text-neutral6 truncate font-medium\">{title}</span>\n </span>\n);\n\nconst scrollTaskIntoView = (node: HTMLLIElement | null) => {\n if (typeof node?.scrollIntoView === 'function') node.scrollIntoView({ block: 'nearest' });\n};\n\nexport interface TaskListProps extends Omit<ComponentProps<typeof TaskListContainer>, 'children' | 'title'> {\n tasks: TaskListItem[];\n title?: ReactNode;\n hideWhenEmpty?: boolean;\n hideWhenComplete?: boolean;\n scrollActiveIntoView?: boolean;\n defaultOpen?: boolean;\n}\n\nexport const TaskList = ({\n tasks,\n title = 'Tasks',\n hideWhenEmpty = true,\n hideWhenComplete = true,\n scrollActiveIntoView = true,\n defaultOpen = true,\n ...props\n}: TaskListProps) => {\n const [open, setOpen] = useState(defaultOpen);\n const activeTask = tasks.find(task => task.status === 'in_progress');\n const summaryTask = activeTask ?? tasks.find(task => task.status === 'pending');\n const completed = tasks.filter(task => task.status === 'completed').length;\n const total = tasks.length;\n\n if ((hideWhenEmpty && total === 0) || (hideWhenComplete && total > 0 && completed === total)) return null;\n\n return (\n <TaskListContainer aria-label=\"Task list\" data-testid=\"task-list\" {...props}>\n <Collapsible open={open} onOpenChange={setOpen}>\n <TaskListHeader>\n <ChevronRight className=\"size-3.5 shrink-0\" />\n {open || !summaryTask ? <TaskListTitle title={title} /> : <TaskListSummary task={summaryTask} />}\n <TaskListCount completed={completed} total={total} />\n </TaskListHeader>\n <CollapsibleContent>\n <TaskListProgress completed={completed} total={total} />\n <ScrollArea maxHeight=\"8rem\" viewPortClassName=\"pr-1\">\n <ul className=\"space-y-1\">\n {tasks.map(task => (\n <TaskListRow\n key={task.id}\n ref={scrollActiveIntoView && task.id === activeTask?.id ? scrollTaskIntoView : undefined}\n task={task}\n />\n ))}\n </ul>\n </ScrollArea>\n </CollapsibleContent>\n </Collapsible>\n </TaskListContainer>\n );\n};\n"],"names":[],"mappings":"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"}
@@ -1,8 +1,9 @@
1
1
  import { TaskItem } from '@mastra/core/signals';
2
2
  import { ComponentProps, ReactNode } from 'react';
3
+ import { CollapsibleTrigger } from '../../Collapsible';
3
4
  export type TaskListItem = TaskItem;
4
5
  export declare const TaskListContainer: ({ className, ...props }: ComponentProps<"section">) => import("react").JSX.Element;
5
- export declare const TaskListHeader: ({ className, ...props }: ComponentProps<"header">) => import("react").JSX.Element;
6
+ export declare const TaskListHeader: ({ className, ...props }: ComponentProps<typeof CollapsibleTrigger>) => import("react").JSX.Element;
6
7
  export interface TaskListCountProps extends ComponentProps<'span'> {
7
8
  completed: number;
8
9
  total: number;
@@ -27,5 +28,6 @@ export interface TaskListProps extends Omit<ComponentProps<typeof TaskListContai
27
28
  hideWhenEmpty?: boolean;
28
29
  hideWhenComplete?: boolean;
29
30
  scrollActiveIntoView?: boolean;
31
+ defaultOpen?: boolean;
30
32
  }
31
- export declare const TaskList: ({ tasks, title, hideWhenEmpty, hideWhenComplete, scrollActiveIntoView, ...props }: TaskListProps) => import("react").JSX.Element | null;
33
+ export declare const TaskList: ({ tasks, title, hideWhenEmpty, hideWhenComplete, scrollActiveIntoView, defaultOpen, ...props }: TaskListProps) => import("react").JSX.Element | null;
@@ -5,5 +5,7 @@ export default meta;
5
5
  type Story = StoryObj<typeof TaskList>;
6
6
  export declare const MixedProgress: Story;
7
7
  export declare const OneActiveTask: Story;
8
+ export declare const Collapsed: Story;
9
+ export declare const LongList: Story;
8
10
  export declare const Empty: Story;
9
11
  export declare const Completed: Story;
package/dist/style.css CHANGED
@@ -1681,10 +1681,6 @@
1681
1681
  height: var(--height-table-header);
1682
1682
  }
1683
1683
 
1684
- .max-h-32 {
1685
- max-height: var(--spacing-32);
1686
- }
1687
-
1688
1684
  .max-h-64 {
1689
1685
  max-height: var(--spacing-64);
1690
1686
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@mastra/playground-ui",
3
3
  "type": "module",
4
- "version": "48.0.0",
4
+ "version": "48.1.0-alpha.0",
5
5
  "description": "Mastra Playground components",
6
6
  "sideEffects": [
7
7
  "**/*.css"
@@ -150,8 +150,8 @@
150
150
  "react": ">=19.0.0",
151
151
  "react-dom": ">=19.0.0",
152
152
  "tailwindcss": "^4.0.0",
153
- "@mastra/client-js": "^1.39.0",
154
- "@mastra/react": "1.4.2"
153
+ "@mastra/client-js": "^1.39.1-alpha.0",
154
+ "@mastra/react": "1.4.3-alpha.0"
155
155
  },
156
156
  "devDependencies": {
157
157
  "@storybook/addon-a11y": "^10.4.1",
@@ -190,10 +190,10 @@
190
190
  "vite-plugin-lib-inject-css": "^2.2.2",
191
191
  "vitest": "4.1.10",
192
192
  "@internal/lint": "0.0.122",
193
- "@mastra/client-js": "^1.39.0",
193
+ "@mastra/client-js": "^1.39.1-alpha.0",
194
194
  "@mastra/memory": "1.26.1",
195
- "@mastra/core": "1.58.0",
196
- "@mastra/react": "1.4.2"
195
+ "@mastra/core": "1.59.0-alpha.0",
196
+ "@mastra/react": "1.4.3-alpha.0"
197
197
  },
198
198
  "homepage": "https://mastra.ai",
199
199
  "repository": {