@mastra/playground-ui 50.1.0-alpha.2 → 51.0.0-alpha.4

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,33 @@
1
1
  # @mastra/playground-ui
2
2
 
3
+ ## 51.0.0-alpha.4
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies:
8
+ - @mastra/core@1.61.0-alpha.4
9
+ - @mastra/client-js@1.42.0-alpha.4
10
+ - @mastra/react@1.4.5-alpha.4
11
+
12
+ ## 51.0.0-alpha.3
13
+
14
+ ### Minor Changes
15
+
16
+ - Added controlled theme selection to Sankey signals so host applications can persist and restore the open theme panel. ([#21968](https://github.com/mastra-ai/mastra/pull/21968))
17
+
18
+ ### Patch Changes
19
+
20
+ - Improved floating surfaces with softer, consistent elevation. ([#21980](https://github.com/mastra-ai/mastra/pull/21980))
21
+
22
+ - Improved plan cards to show expansion controls only when content is clipped and keep approval actions readable. ([#21891](https://github.com/mastra-ai/mastra/pull/21891))
23
+
24
+ - Aligned the `flat` and `factory` Section layouts so their headings, row content, and actions share consistent horizontal edges. ([#21970](https://github.com/mastra-ai/mastra/pull/21970))
25
+
26
+ - Updated dependencies [[`26d4016`](https://github.com/mastra-ai/mastra/commit/26d40160ff7f7d8bf95fee2039a52cbc83863533), [`9267e9b`](https://github.com/mastra-ai/mastra/commit/9267e9b3d9c2fcf16936050495a787054c2431ab), [`acc3471`](https://github.com/mastra-ai/mastra/commit/acc3471de5f3fde8027ee4e355af292b2bc1bc30), [`b6a771e`](https://github.com/mastra-ai/mastra/commit/b6a771ef23d203ddb348efca8065eff65def8191), [`9267e9b`](https://github.com/mastra-ai/mastra/commit/9267e9b3d9c2fcf16936050495a787054c2431ab), [`26d4016`](https://github.com/mastra-ai/mastra/commit/26d40160ff7f7d8bf95fee2039a52cbc83863533), [`9267e9b`](https://github.com/mastra-ai/mastra/commit/9267e9b3d9c2fcf16936050495a787054c2431ab), [`9267e9b`](https://github.com/mastra-ai/mastra/commit/9267e9b3d9c2fcf16936050495a787054c2431ab), [`57c5103`](https://github.com/mastra-ai/mastra/commit/57c51035a2a36e3df3c4f32f46bb789a66ed5946)]:
27
+ - @mastra/client-js@1.42.0-alpha.3
28
+ - @mastra/core@1.61.0-alpha.3
29
+ - @mastra/react@1.4.5-alpha.3
30
+
3
31
  ## 50.1.0-alpha.2
4
32
 
5
33
  ### Minor Changes
@@ -2,7 +2,7 @@
2
2
 
3
3
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4
4
 
5
- const section = require('../section-DTGcmyrv.cjs');
5
+ const section = require('../section-CVHYJHNG.cjs');
6
6
 
7
7
 
8
8
 
@@ -1,2 +1,2 @@
1
- export { S as Section, a as SectionRoot, b as SubSectionRoot } from '../section-BoL2PFeq.js';
1
+ export { S as Section, a as SectionRoot, b as SubSectionRoot } from '../section-CnLkFJwn.js';
2
2
  //# sourceMappingURL=Section.es.js.map
@@ -14,7 +14,7 @@ const React = require('react');
14
14
  const Button = require('../Button-BWj3opYd.cjs');
15
15
  const buttonsGroup = require('../buttons-group-w9QHUGVh.cjs');
16
16
  const copyButton = require('../copy-button-CP3uo8ID.cjs');
17
- const section = require('../section-DTGcmyrv.cjs');
17
+ const section = require('../section-CVHYJHNG.cjs');
18
18
  const themeProvider = require('../theme-provider-aO5-jZVp.cjs');
19
19
  const drawer = require('../drawer-C_94EZS7.cjs');
20
20
  const utils_cn = require('../cn-vA5sWo9W.cjs');
@@ -11,7 +11,7 @@ import { useState, useMemo } from 'react';
11
11
  import { B as Button } from '../Button-XHy01fYR.js';
12
12
  import { B as ButtonsGroup } from '../buttons-group-D01G8mAW.js';
13
13
  import { C as CopyButton } from '../copy-button-7bJude5U.js';
14
- import { S as Section } from '../section-BoL2PFeq.js';
14
+ import { S as Section } from '../section-CnLkFJwn.js';
15
15
  import { u as useTheme } from '../theme-provider-C9ih9jSS.js';
16
16
  import { j as DrawerInteractive, D as Drawer, l as DrawerPortal, a as DrawerBackdrop, q as DrawerViewport, k as DrawerPopup, o as DrawerTitle, e as DrawerDescription, c as DrawerClose } from '../drawer-D-9g5Fgx.js';
17
17
  import { c as cn } from '../cn-BakJzhuv.js';
@@ -24,12 +24,15 @@ const usePlanContext = () => {
24
24
  };
25
25
  function Plan({ children, collapsedHeight = DEFAULT_COLLAPSED_HEIGHT, className, ...props }) {
26
26
  const [isExpanded, setIsExpanded] = React.useState(false);
27
+ const [isClipped, setClipped] = React.useState(false);
27
28
  const toggleExpanded = () => {
28
29
  setIsExpanded((current) => !current);
29
30
  };
30
31
  const contextValue = {
31
32
  collapsedHeight,
32
33
  isExpanded,
34
+ isClipped,
35
+ setClipped,
33
36
  toggleExpanded
34
37
  };
35
38
  return /* @__PURE__ */ jsxRuntime.jsx(PlanContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxRuntime.jsx("div", { "data-slot": "plan", className: utils_cn.cn("w-full overflow-hidden rounded-xl bg-surface3", className), ...props, children }) });
@@ -108,15 +111,40 @@ function PlanMain({ children, className, ...props }) {
108
111
  return /* @__PURE__ */ jsxRuntime.jsx("div", { "data-slot": "plan-main", className: utils_cn.cn("relative", className), ...props, children });
109
112
  }
110
113
  function PlanContent({ children, className, style, ...props }) {
111
- const { collapsedHeight, isExpanded } = usePlanContext();
114
+ const { collapsedHeight, isExpanded, isClipped, setClipped } = usePlanContext();
115
+ const contentRef = React.useRef(null);
116
+ React.useLayoutEffect(() => {
117
+ const element = contentRef.current;
118
+ if (!element) return;
119
+ const measure = () => setClipped(element.scrollHeight > collapsedHeight);
120
+ measure();
121
+ if (typeof ResizeObserver === "undefined") return;
122
+ const observer = new ResizeObserver(measure);
123
+ observer.observe(element);
124
+ return () => observer.disconnect();
125
+ }, [children, collapsedHeight, setClipped]);
126
+ const showClipHint = !isExpanded && isClipped;
112
127
  return /* @__PURE__ */ jsxRuntime.jsx(
113
128
  "div",
114
129
  {
115
130
  "data-slot": "plan-content",
116
- className: utils_cn.cn("relative", !isExpanded && "overflow-hidden", className),
131
+ ...showClipHint ? { "data-clipped": "" } : {},
132
+ className: utils_cn.cn(
133
+ "relative",
134
+ !isExpanded && "overflow-hidden",
135
+ showClipHint && "mask-b-from-60% mask-b-to-100%",
136
+ className
137
+ ),
117
138
  style: !isExpanded ? { ...style, maxHeight: collapsedHeight } : style,
118
139
  ...props,
119
- children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "[&_code]:bg-surface4 [&_h1]:text-header-md [&_h1]:leading-header-md [&_h2]:text-header-sm [&_h2]:leading-header-sm [&_h3]:text-ui-lg [&_h3]:leading-ui-lg [&_p]:text-ui-md [&_p]:leading-6", children: /* @__PURE__ */ jsxRuntime.jsx(markdownRenderer.MarkdownRenderer, { className: "text-neutral6", children }) })
140
+ children: /* @__PURE__ */ jsxRuntime.jsx(
141
+ "div",
142
+ {
143
+ ref: contentRef,
144
+ className: "[&_code]:bg-surface4 [&_h1]:text-header-md [&_h1]:leading-header-md [&_h2]:text-header-sm [&_h2]:leading-header-sm [&_h3]:text-ui-lg [&_h3]:leading-ui-lg [&_p]:text-ui-md [&_p]:leading-6",
145
+ children: /* @__PURE__ */ jsxRuntime.jsx(markdownRenderer.MarkdownRenderer, { className: "text-neutral6", children })
146
+ }
147
+ )
120
148
  }
121
149
  );
122
150
  }
@@ -128,13 +156,22 @@ function PlanFile({ children, className, ...props }) {
128
156
  }
129
157
  function PlanControls({ children, className, ...props }) {
130
158
  const hasActions = Boolean(children);
131
- return /* @__PURE__ */ jsxRuntime.jsx("div", { "data-slot": "plan-controls", className: utils_cn.cn("relative z-10 mt-4 flex justify-center", className), ...props, children: hasActions ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid w-full max-w-sm grid-cols-[1fr_auto_1fr] items-center gap-2 px-10", children }) : /* @__PURE__ */ jsxRuntime.jsx(PlanExpandButton, {}) });
159
+ return /* @__PURE__ */ jsxRuntime.jsx(
160
+ "div",
161
+ {
162
+ "data-slot": "plan-controls",
163
+ className: utils_cn.cn("relative z-10 mt-4 flex justify-center empty:hidden", className),
164
+ ...props,
165
+ children: hasActions ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid w-full max-w-sm grid-cols-[1fr_auto_1fr] items-center gap-2 px-10", children }) : /* @__PURE__ */ jsxRuntime.jsx(PlanExpandButton, {})
166
+ }
167
+ );
132
168
  }
133
169
  function PlanActionGroup({ children, className, ...props }) {
134
170
  return /* @__PURE__ */ jsxRuntime.jsx("div", { "data-slot": "plan-action-group", className: utils_cn.cn("flex justify-start gap-2 empty:hidden", className), ...props, children });
135
171
  }
136
172
  function PlanExpandButton({ className, ...props }) {
137
- const { isExpanded, toggleExpanded } = usePlanContext();
173
+ const { isExpanded, isClipped, toggleExpanded } = usePlanContext();
174
+ if (!isClipped && !isExpanded) return null;
138
175
  return /* @__PURE__ */ jsxRuntime.jsxs(
139
176
  Button.Button,
140
177
  {
@@ -1 +1 @@
1
- {"version":3,"file":"plan.cjs.js","sources":["../../../src/ds/components/ai/plan/plan.tsx"],"sourcesContent":["import { CheckIcon, ClipboardList, CopyIcon, Maximize2, Minimize2 } from 'lucide-react';\nimport { createContext, useContext, useState } from 'react';\nimport type { ComponentProps, ReactNode } from 'react';\n\nimport { Badge } from '@/ds/components/Badge';\nimport { Button } from '@/ds/components/Button';\nimport { MarkdownRenderer } from '@/ds/components/MarkdownRenderer';\nimport { Txt } from '@/ds/components/Txt';\nimport { Icon } from '@/ds/icons/Icon';\nimport { useCopyToClipboard } from '@/hooks/use-copy-to-clipboard';\nimport { cn } from '@/lib/utils';\n\nconst DEFAULT_COLLAPSED_HEIGHT = 220;\n\ninterface PlanContextValue {\n collapsedHeight: number;\n isExpanded: boolean;\n toggleExpanded: () => void;\n}\n\nconst PlanContext = createContext<PlanContextValue | null>(null);\n\nconst usePlanContext = () => {\n const context = useContext(PlanContext);\n\n if (!context) {\n throw new Error('Plan compound components must be rendered inside <Plan>.');\n }\n\n return context;\n};\n\nexport interface PlanProps extends ComponentProps<'div'> {\n collapsedHeight?: number;\n}\n\nexport function Plan({ children, collapsedHeight = DEFAULT_COLLAPSED_HEIGHT, className, ...props }: PlanProps) {\n const [isExpanded, setIsExpanded] = useState(false);\n\n const toggleExpanded = () => {\n setIsExpanded(current => !current);\n };\n\n const contextValue = {\n collapsedHeight,\n isExpanded,\n toggleExpanded,\n };\n\n return (\n <PlanContext.Provider value={contextValue}>\n <div data-slot=\"plan\" className={cn('w-full overflow-hidden rounded-xl bg-surface3', className)} {...props}>\n {children}\n </div>\n </PlanContext.Provider>\n );\n}\n\nexport type PlanHeaderProps = ComponentProps<'div'>;\n\nexport function PlanHeader({ children, className, ...props }: PlanHeaderProps) {\n return (\n <div\n data-slot=\"plan-header\"\n className={cn('flex min-h-10 items-center justify-between gap-3 px-4 pt-3', className)}\n {...props}\n >\n {children}\n </div>\n );\n}\n\nexport type PlanLabelProps = ComponentProps<'div'>;\n\nexport function PlanLabel({ children = 'Plan', className, ...props }: PlanLabelProps) {\n return (\n <div data-slot=\"plan-label\" className={cn('flex min-w-0 items-center gap-2', className)} {...props}>\n <Icon size=\"sm\" className=\"text-icon3\">\n <ClipboardList />\n </Icon>\n <Txt as=\"span\" variant=\"ui-sm\" className=\"text-neutral4\">\n {children}\n </Txt>\n </div>\n );\n}\n\nexport type PlanHeaderActionsProps = ComponentProps<'div'>;\n\nexport function PlanHeaderActions({ children, className, ...props }: PlanHeaderActionsProps) {\n return (\n <div data-slot=\"plan-header-actions\" className={cn('flex shrink-0 items-center gap-1', className)} {...props}>\n {children}\n </div>\n );\n}\n\nexport type PlanStatusProps = Omit<ComponentProps<typeof Badge>, 'icon' | 'size'>;\n\nexport function PlanStatus({ children, variant = 'default', ...props }: PlanStatusProps) {\n return (\n <Badge {...props} variant={variant} size=\"xs\" icon={<span className=\"size-1 rounded-full bg-current\" />}>\n {children}\n </Badge>\n );\n}\n\nexport interface PlanCopyButtonProps extends Omit<\n ComponentProps<typeof Button>,\n 'aria-label' | 'children' | 'onClick' | 'size' | 'tooltip' | 'type' | 'variant'\n> {\n content: string;\n}\n\nexport function PlanCopyButton({ content, ...props }: PlanCopyButtonProps) {\n const { isCopied, handleCopy } = useCopyToClipboard({\n text: content,\n copiedDuration: 1500,\n showToast: false,\n });\n\n return (\n <Button\n {...props}\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-sm\"\n tooltip=\"Copy plan\"\n aria-label=\"Copy plan\"\n onClick={handleCopy}\n >\n {isCopied ? <CheckIcon /> : <CopyIcon />}\n </Button>\n );\n}\n\nexport type PlanBodyProps = ComponentProps<'div'>;\n\nexport function PlanBody({ children, className, ...props }: PlanBodyProps) {\n return (\n <div data-slot=\"plan-body\" className={cn('px-5 pt-4 pb-5', className)} {...props}>\n {children}\n </div>\n );\n}\n\nexport type PlanIntroProps = ComponentProps<'div'>;\n\nexport function PlanIntro({ children, className, ...props }: PlanIntroProps) {\n return (\n <div data-slot=\"plan-intro\" className={cn('mb-5 space-y-1', className)} {...props}>\n {children}\n </div>\n );\n}\n\nexport interface PlanTitleProps extends Omit<ComponentProps<typeof Txt>, 'as' | 'children' | 'variant'> {\n children: ReactNode;\n}\n\nexport function PlanTitle({ children, className, ...props }: PlanTitleProps) {\n return (\n <Txt {...props} as=\"h3\" variant=\"header-sm\" className={cn('text-neutral7 font-semibold', className)}>\n {children}\n </Txt>\n );\n}\n\nexport interface PlanPathProps extends Omit<\n ComponentProps<typeof Txt>,\n 'as' | 'children' | 'font' | 'title' | 'variant'\n> {\n children: string;\n}\n\nconst getFileName = (path: string) => {\n const segments = path.split(/[\\\\/]/).filter(Boolean);\n return segments[segments.length - 1] ?? path;\n};\n\nexport function PlanPath({ children, className, ...props }: PlanPathProps) {\n return (\n <Txt\n {...props}\n as=\"p\"\n variant=\"ui-xs\"\n font=\"mono\"\n title={children}\n className={cn('max-w-full truncate overflow-hidden text-neutral3', className)}\n >\n {getFileName(children)}\n </Txt>\n );\n}\n\nexport type PlanMainProps = ComponentProps<'div'>;\n\nexport function PlanMain({ children, className, ...props }: PlanMainProps) {\n return (\n <div data-slot=\"plan-main\" className={cn('relative', className)} {...props}>\n {children}\n </div>\n );\n}\n\nexport interface PlanContentProps extends Omit<ComponentProps<'div'>, 'children'> {\n children: string;\n}\n\nexport function PlanContent({ children, className, style, ...props }: PlanContentProps) {\n const { collapsedHeight, isExpanded } = usePlanContext();\n\n return (\n <div\n data-slot=\"plan-content\"\n className={cn('relative', !isExpanded && 'overflow-hidden', className)}\n style={!isExpanded ? { ...style, maxHeight: collapsedHeight } : style}\n {...props}\n >\n <div className=\"[&_code]:bg-surface4 [&_h1]:text-header-md [&_h1]:leading-header-md [&_h2]:text-header-sm [&_h2]:leading-header-sm [&_h3]:text-ui-lg [&_h3]:leading-ui-lg [&_p]:text-ui-md [&_p]:leading-6\">\n <MarkdownRenderer className=\"text-neutral6\">{children}</MarkdownRenderer>\n </div>\n </div>\n );\n}\n\nexport interface PlanFileProps extends Omit<ComponentProps<'div'>, 'children'> {\n children: string;\n}\n\nexport function PlanFile({ children, className, ...props }: PlanFileProps) {\n return (\n <div data-slot=\"plan-file\" className={className} {...props}>\n <Txt as=\"p\" variant=\"ui-xs\" className=\"text-neutral3 mb-2\">\n Plan file\n </Txt>\n <Txt as=\"p\" variant=\"ui-sm\" className=\"text-neutral6 font-mono break-all\">\n {children}\n </Txt>\n </div>\n );\n}\n\nexport type PlanControlsProps = ComponentProps<'div'>;\n\nexport function PlanControls({ children, className, ...props }: PlanControlsProps) {\n const hasActions = Boolean(children);\n\n return (\n <div data-slot=\"plan-controls\" className={cn('relative z-10 mt-4 flex justify-center', className)} {...props}>\n {hasActions ? (\n <div className=\"grid w-full max-w-sm grid-cols-[1fr_auto_1fr] items-center gap-2 px-10\">{children}</div>\n ) : (\n <PlanExpandButton />\n )}\n </div>\n );\n}\n\nexport type PlanActionGroupProps = ComponentProps<'div'>;\n\nexport function PlanActionGroup({ children, className, ...props }: PlanActionGroupProps) {\n return (\n <div data-slot=\"plan-action-group\" className={cn('flex justify-start gap-2 empty:hidden', className)} {...props}>\n {children}\n </div>\n );\n}\n\nexport type PlanExpandButtonProps = Omit<\n ComponentProps<typeof Button>,\n 'aria-label' | 'children' | 'onClick' | 'size' | 'type' | 'variant'\n>;\n\nexport function PlanExpandButton({ className, ...props }: PlanExpandButtonProps) {\n const { isExpanded, toggleExpanded } = usePlanContext();\n\n return (\n <Button\n {...props}\n className={cn('shrink-0 whitespace-nowrap', className)}\n type=\"button\"\n variant=\"default\"\n size=\"sm\"\n aria-label={isExpanded ? 'Collapse plan' : 'Expand plan'}\n onClick={toggleExpanded}\n >\n {isExpanded ? <Minimize2 /> : <Maximize2 />}\n {isExpanded ? 'Collapse plan' : 'Expand plan'}\n </Button>\n );\n}\n"],"names":["createContext","useContext","useState","cn","jsx","jsxs","Icon","ClipboardList","Txt","Badge","useCopyToClipboard","Button","CheckIcon","CopyIcon","MarkdownRenderer","Minimize2","Maximize2"],"mappings":"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"}
1
+ {"version":3,"file":"plan.cjs.js","sources":["../../../src/ds/components/ai/plan/plan.tsx"],"sourcesContent":["import { CheckIcon, ClipboardList, CopyIcon, Maximize2, Minimize2 } from 'lucide-react';\nimport { createContext, useContext, useLayoutEffect, useRef, useState } from 'react';\nimport type { ComponentProps, ReactNode } from 'react';\n\nimport { Badge } from '@/ds/components/Badge';\nimport { Button } from '@/ds/components/Button';\nimport { MarkdownRenderer } from '@/ds/components/MarkdownRenderer';\nimport { Txt } from '@/ds/components/Txt';\nimport { Icon } from '@/ds/icons/Icon';\nimport { useCopyToClipboard } from '@/hooks/use-copy-to-clipboard';\nimport { cn } from '@/lib/utils';\n\nconst DEFAULT_COLLAPSED_HEIGHT = 220;\n\ninterface PlanContextValue {\n collapsedHeight: number;\n isExpanded: boolean;\n /** Whether the rendered content overflows the collapsed height (measured, not estimated). */\n isClipped: boolean;\n setClipped: (clipped: boolean) => void;\n toggleExpanded: () => void;\n}\n\nconst PlanContext = createContext<PlanContextValue | null>(null);\n\nconst usePlanContext = () => {\n const context = useContext(PlanContext);\n\n if (!context) {\n throw new Error('Plan compound components must be rendered inside <Plan>.');\n }\n\n return context;\n};\n\nexport interface PlanProps extends ComponentProps<'div'> {\n collapsedHeight?: number;\n}\n\nexport function Plan({ children, collapsedHeight = DEFAULT_COLLAPSED_HEIGHT, className, ...props }: PlanProps) {\n const [isExpanded, setIsExpanded] = useState(false);\n const [isClipped, setClipped] = useState(false);\n\n const toggleExpanded = () => {\n setIsExpanded(current => !current);\n };\n\n const contextValue = {\n collapsedHeight,\n isExpanded,\n isClipped,\n setClipped,\n toggleExpanded,\n };\n\n return (\n <PlanContext.Provider value={contextValue}>\n <div data-slot=\"plan\" className={cn('w-full overflow-hidden rounded-xl bg-surface3', className)} {...props}>\n {children}\n </div>\n </PlanContext.Provider>\n );\n}\n\nexport type PlanHeaderProps = ComponentProps<'div'>;\n\nexport function PlanHeader({ children, className, ...props }: PlanHeaderProps) {\n return (\n <div\n data-slot=\"plan-header\"\n className={cn('flex min-h-10 items-center justify-between gap-3 px-4 pt-3', className)}\n {...props}\n >\n {children}\n </div>\n );\n}\n\nexport type PlanLabelProps = ComponentProps<'div'>;\n\nexport function PlanLabel({ children = 'Plan', className, ...props }: PlanLabelProps) {\n return (\n <div data-slot=\"plan-label\" className={cn('flex min-w-0 items-center gap-2', className)} {...props}>\n <Icon size=\"sm\" className=\"text-icon3\">\n <ClipboardList />\n </Icon>\n <Txt as=\"span\" variant=\"ui-sm\" className=\"text-neutral4\">\n {children}\n </Txt>\n </div>\n );\n}\n\nexport type PlanHeaderActionsProps = ComponentProps<'div'>;\n\nexport function PlanHeaderActions({ children, className, ...props }: PlanHeaderActionsProps) {\n return (\n <div data-slot=\"plan-header-actions\" className={cn('flex shrink-0 items-center gap-1', className)} {...props}>\n {children}\n </div>\n );\n}\n\nexport type PlanStatusProps = Omit<ComponentProps<typeof Badge>, 'icon' | 'size'>;\n\nexport function PlanStatus({ children, variant = 'default', ...props }: PlanStatusProps) {\n return (\n <Badge {...props} variant={variant} size=\"xs\" icon={<span className=\"size-1 rounded-full bg-current\" />}>\n {children}\n </Badge>\n );\n}\n\nexport interface PlanCopyButtonProps extends Omit<\n ComponentProps<typeof Button>,\n 'aria-label' | 'children' | 'onClick' | 'size' | 'tooltip' | 'type' | 'variant'\n> {\n content: string;\n}\n\nexport function PlanCopyButton({ content, ...props }: PlanCopyButtonProps) {\n const { isCopied, handleCopy } = useCopyToClipboard({\n text: content,\n copiedDuration: 1500,\n showToast: false,\n });\n\n return (\n <Button\n {...props}\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-sm\"\n tooltip=\"Copy plan\"\n aria-label=\"Copy plan\"\n onClick={handleCopy}\n >\n {isCopied ? <CheckIcon /> : <CopyIcon />}\n </Button>\n );\n}\n\nexport type PlanBodyProps = ComponentProps<'div'>;\n\nexport function PlanBody({ children, className, ...props }: PlanBodyProps) {\n return (\n <div data-slot=\"plan-body\" className={cn('px-5 pt-4 pb-5', className)} {...props}>\n {children}\n </div>\n );\n}\n\nexport type PlanIntroProps = ComponentProps<'div'>;\n\nexport function PlanIntro({ children, className, ...props }: PlanIntroProps) {\n return (\n <div data-slot=\"plan-intro\" className={cn('mb-5 space-y-1', className)} {...props}>\n {children}\n </div>\n );\n}\n\nexport interface PlanTitleProps extends Omit<ComponentProps<typeof Txt>, 'as' | 'children' | 'variant'> {\n children: ReactNode;\n}\n\nexport function PlanTitle({ children, className, ...props }: PlanTitleProps) {\n return (\n <Txt {...props} as=\"h3\" variant=\"header-sm\" className={cn('text-neutral7 font-semibold', className)}>\n {children}\n </Txt>\n );\n}\n\nexport interface PlanPathProps extends Omit<\n ComponentProps<typeof Txt>,\n 'as' | 'children' | 'font' | 'title' | 'variant'\n> {\n children: string;\n}\n\nconst getFileName = (path: string) => {\n const segments = path.split(/[\\\\/]/).filter(Boolean);\n return segments[segments.length - 1] ?? path;\n};\n\nexport function PlanPath({ children, className, ...props }: PlanPathProps) {\n return (\n <Txt\n {...props}\n as=\"p\"\n variant=\"ui-xs\"\n font=\"mono\"\n title={children}\n className={cn('max-w-full truncate overflow-hidden text-neutral3', className)}\n >\n {getFileName(children)}\n </Txt>\n );\n}\n\nexport type PlanMainProps = ComponentProps<'div'>;\n\nexport function PlanMain({ children, className, ...props }: PlanMainProps) {\n return (\n <div data-slot=\"plan-main\" className={cn('relative', className)} {...props}>\n {children}\n </div>\n );\n}\n\nexport interface PlanContentProps extends Omit<ComponentProps<'div'>, 'children'> {\n children: string;\n}\n\nexport function PlanContent({ children, className, style, ...props }: PlanContentProps) {\n const { collapsedHeight, isExpanded, isClipped, setClipped } = usePlanContext();\n const contentRef = useRef<HTMLDivElement>(null);\n\n // Measure the rendered content against the collapsed height so the clip hint\n // and expand control track actual overflow — not an estimate of it.\n useLayoutEffect(() => {\n const element = contentRef.current;\n if (!element) return;\n\n const measure = () => setClipped(element.scrollHeight > collapsedHeight);\n measure();\n\n if (typeof ResizeObserver === 'undefined') return;\n const observer = new ResizeObserver(measure);\n observer.observe(element);\n return () => observer.disconnect();\n }, [children, collapsedHeight, setClipped]);\n\n const showClipHint = !isExpanded && isClipped;\n\n return (\n <div\n data-slot=\"plan-content\"\n // The clip hint masks the content itself, so it reads correctly on any card background.\n {...(showClipHint ? { 'data-clipped': '' } : {})}\n className={cn(\n 'relative',\n !isExpanded && 'overflow-hidden',\n showClipHint && 'mask-b-from-60% mask-b-to-100%',\n className,\n )}\n style={!isExpanded ? { ...style, maxHeight: collapsedHeight } : style}\n {...props}\n >\n <div\n ref={contentRef}\n className=\"[&_code]:bg-surface4 [&_h1]:text-header-md [&_h1]:leading-header-md [&_h2]:text-header-sm [&_h2]:leading-header-sm [&_h3]:text-ui-lg [&_h3]:leading-ui-lg [&_p]:text-ui-md [&_p]:leading-6\"\n >\n <MarkdownRenderer className=\"text-neutral6\">{children}</MarkdownRenderer>\n </div>\n </div>\n );\n}\n\nexport interface PlanFileProps extends Omit<ComponentProps<'div'>, 'children'> {\n children: string;\n}\n\nexport function PlanFile({ children, className, ...props }: PlanFileProps) {\n return (\n <div data-slot=\"plan-file\" className={className} {...props}>\n <Txt as=\"p\" variant=\"ui-xs\" className=\"text-neutral3 mb-2\">\n Plan file\n </Txt>\n <Txt as=\"p\" variant=\"ui-sm\" className=\"text-neutral6 font-mono break-all\">\n {children}\n </Txt>\n </div>\n );\n}\n\nexport type PlanControlsProps = ComponentProps<'div'>;\n\nexport function PlanControls({ children, className, ...props }: PlanControlsProps) {\n const hasActions = Boolean(children);\n\n return (\n <div\n data-slot=\"plan-controls\"\n className={cn('relative z-10 mt-4 flex justify-center empty:hidden', className)}\n {...props}\n >\n {hasActions ? (\n <div className=\"grid w-full max-w-sm grid-cols-[1fr_auto_1fr] items-center gap-2 px-10\">{children}</div>\n ) : (\n <PlanExpandButton />\n )}\n </div>\n );\n}\n\nexport type PlanActionGroupProps = ComponentProps<'div'>;\n\nexport function PlanActionGroup({ children, className, ...props }: PlanActionGroupProps) {\n return (\n <div data-slot=\"plan-action-group\" className={cn('flex justify-start gap-2 empty:hidden', className)} {...props}>\n {children}\n </div>\n );\n}\n\nexport type PlanExpandButtonProps = Omit<\n ComponentProps<typeof Button>,\n 'aria-label' | 'children' | 'onClick' | 'size' | 'type' | 'variant'\n>;\n\nexport function PlanExpandButton({ className, ...props }: PlanExpandButtonProps) {\n const { isExpanded, isClipped, toggleExpanded } = usePlanContext();\n\n // Nothing to expand: the collapsed card already shows the whole plan.\n if (!isClipped && !isExpanded) return null;\n\n return (\n <Button\n {...props}\n className={cn('shrink-0 whitespace-nowrap', className)}\n type=\"button\"\n variant=\"default\"\n size=\"sm\"\n aria-label={isExpanded ? 'Collapse plan' : 'Expand plan'}\n onClick={toggleExpanded}\n >\n {isExpanded ? <Minimize2 /> : <Maximize2 />}\n {isExpanded ? 'Collapse plan' : 'Expand plan'}\n </Button>\n );\n}\n"],"names":["createContext","useContext","useState","cn","jsx","jsxs","Icon","ClipboardList","Txt","Badge","useCopyToClipboard","Button","CheckIcon","CopyIcon","useRef","useLayoutEffect","MarkdownRenderer","Minimize2","Maximize2"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { jsx, jsxs } from 'react/jsx-runtime';
2
2
  import { CheckIcon, CopyIcon, Minimize2, Maximize2, ClipboardList } from 'lucide-react';
3
- import { useState, createContext, useContext } from 'react';
3
+ import { useState, useRef, useLayoutEffect, createContext, useContext } from 'react';
4
4
  import { B as Badge } from '../../Badge-woV6OD8k.js';
5
5
  import { B as Button } from '../../Button-XHy01fYR.js';
6
6
  import { M as MarkdownRenderer } from '../../markdown-renderer-ByRLqDFg.js';
@@ -20,12 +20,15 @@ const usePlanContext = () => {
20
20
  };
21
21
  function Plan({ children, collapsedHeight = DEFAULT_COLLAPSED_HEIGHT, className, ...props }) {
22
22
  const [isExpanded, setIsExpanded] = useState(false);
23
+ const [isClipped, setClipped] = useState(false);
23
24
  const toggleExpanded = () => {
24
25
  setIsExpanded((current) => !current);
25
26
  };
26
27
  const contextValue = {
27
28
  collapsedHeight,
28
29
  isExpanded,
30
+ isClipped,
31
+ setClipped,
29
32
  toggleExpanded
30
33
  };
31
34
  return /* @__PURE__ */ jsx(PlanContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx("div", { "data-slot": "plan", className: cn("w-full overflow-hidden rounded-xl bg-surface3", className), ...props, children }) });
@@ -104,15 +107,40 @@ function PlanMain({ children, className, ...props }) {
104
107
  return /* @__PURE__ */ jsx("div", { "data-slot": "plan-main", className: cn("relative", className), ...props, children });
105
108
  }
106
109
  function PlanContent({ children, className, style, ...props }) {
107
- const { collapsedHeight, isExpanded } = usePlanContext();
110
+ const { collapsedHeight, isExpanded, isClipped, setClipped } = usePlanContext();
111
+ const contentRef = useRef(null);
112
+ useLayoutEffect(() => {
113
+ const element = contentRef.current;
114
+ if (!element) return;
115
+ const measure = () => setClipped(element.scrollHeight > collapsedHeight);
116
+ measure();
117
+ if (typeof ResizeObserver === "undefined") return;
118
+ const observer = new ResizeObserver(measure);
119
+ observer.observe(element);
120
+ return () => observer.disconnect();
121
+ }, [children, collapsedHeight, setClipped]);
122
+ const showClipHint = !isExpanded && isClipped;
108
123
  return /* @__PURE__ */ jsx(
109
124
  "div",
110
125
  {
111
126
  "data-slot": "plan-content",
112
- className: cn("relative", !isExpanded && "overflow-hidden", className),
127
+ ...showClipHint ? { "data-clipped": "" } : {},
128
+ className: cn(
129
+ "relative",
130
+ !isExpanded && "overflow-hidden",
131
+ showClipHint && "mask-b-from-60% mask-b-to-100%",
132
+ className
133
+ ),
113
134
  style: !isExpanded ? { ...style, maxHeight: collapsedHeight } : style,
114
135
  ...props,
115
- children: /* @__PURE__ */ jsx("div", { className: "[&_code]:bg-surface4 [&_h1]:text-header-md [&_h1]:leading-header-md [&_h2]:text-header-sm [&_h2]:leading-header-sm [&_h3]:text-ui-lg [&_h3]:leading-ui-lg [&_p]:text-ui-md [&_p]:leading-6", children: /* @__PURE__ */ jsx(MarkdownRenderer, { className: "text-neutral6", children }) })
136
+ children: /* @__PURE__ */ jsx(
137
+ "div",
138
+ {
139
+ ref: contentRef,
140
+ className: "[&_code]:bg-surface4 [&_h1]:text-header-md [&_h1]:leading-header-md [&_h2]:text-header-sm [&_h2]:leading-header-sm [&_h3]:text-ui-lg [&_h3]:leading-ui-lg [&_p]:text-ui-md [&_p]:leading-6",
141
+ children: /* @__PURE__ */ jsx(MarkdownRenderer, { className: "text-neutral6", children })
142
+ }
143
+ )
116
144
  }
117
145
  );
118
146
  }
@@ -124,13 +152,22 @@ function PlanFile({ children, className, ...props }) {
124
152
  }
125
153
  function PlanControls({ children, className, ...props }) {
126
154
  const hasActions = Boolean(children);
127
- return /* @__PURE__ */ jsx("div", { "data-slot": "plan-controls", className: cn("relative z-10 mt-4 flex justify-center", className), ...props, children: hasActions ? /* @__PURE__ */ jsx("div", { className: "grid w-full max-w-sm grid-cols-[1fr_auto_1fr] items-center gap-2 px-10", children }) : /* @__PURE__ */ jsx(PlanExpandButton, {}) });
155
+ return /* @__PURE__ */ jsx(
156
+ "div",
157
+ {
158
+ "data-slot": "plan-controls",
159
+ className: cn("relative z-10 mt-4 flex justify-center empty:hidden", className),
160
+ ...props,
161
+ children: hasActions ? /* @__PURE__ */ jsx("div", { className: "grid w-full max-w-sm grid-cols-[1fr_auto_1fr] items-center gap-2 px-10", children }) : /* @__PURE__ */ jsx(PlanExpandButton, {})
162
+ }
163
+ );
128
164
  }
129
165
  function PlanActionGroup({ children, className, ...props }) {
130
166
  return /* @__PURE__ */ jsx("div", { "data-slot": "plan-action-group", className: cn("flex justify-start gap-2 empty:hidden", className), ...props, children });
131
167
  }
132
168
  function PlanExpandButton({ className, ...props }) {
133
- const { isExpanded, toggleExpanded } = usePlanContext();
169
+ const { isExpanded, isClipped, toggleExpanded } = usePlanContext();
170
+ if (!isClipped && !isExpanded) return null;
134
171
  return /* @__PURE__ */ jsxs(
135
172
  Button,
136
173
  {
@@ -1 +1 @@
1
- {"version":3,"file":"plan.es.js","sources":["../../../src/ds/components/ai/plan/plan.tsx"],"sourcesContent":["import { CheckIcon, ClipboardList, CopyIcon, Maximize2, Minimize2 } from 'lucide-react';\nimport { createContext, useContext, useState } from 'react';\nimport type { ComponentProps, ReactNode } from 'react';\n\nimport { Badge } from '@/ds/components/Badge';\nimport { Button } from '@/ds/components/Button';\nimport { MarkdownRenderer } from '@/ds/components/MarkdownRenderer';\nimport { Txt } from '@/ds/components/Txt';\nimport { Icon } from '@/ds/icons/Icon';\nimport { useCopyToClipboard } from '@/hooks/use-copy-to-clipboard';\nimport { cn } from '@/lib/utils';\n\nconst DEFAULT_COLLAPSED_HEIGHT = 220;\n\ninterface PlanContextValue {\n collapsedHeight: number;\n isExpanded: boolean;\n toggleExpanded: () => void;\n}\n\nconst PlanContext = createContext<PlanContextValue | null>(null);\n\nconst usePlanContext = () => {\n const context = useContext(PlanContext);\n\n if (!context) {\n throw new Error('Plan compound components must be rendered inside <Plan>.');\n }\n\n return context;\n};\n\nexport interface PlanProps extends ComponentProps<'div'> {\n collapsedHeight?: number;\n}\n\nexport function Plan({ children, collapsedHeight = DEFAULT_COLLAPSED_HEIGHT, className, ...props }: PlanProps) {\n const [isExpanded, setIsExpanded] = useState(false);\n\n const toggleExpanded = () => {\n setIsExpanded(current => !current);\n };\n\n const contextValue = {\n collapsedHeight,\n isExpanded,\n toggleExpanded,\n };\n\n return (\n <PlanContext.Provider value={contextValue}>\n <div data-slot=\"plan\" className={cn('w-full overflow-hidden rounded-xl bg-surface3', className)} {...props}>\n {children}\n </div>\n </PlanContext.Provider>\n );\n}\n\nexport type PlanHeaderProps = ComponentProps<'div'>;\n\nexport function PlanHeader({ children, className, ...props }: PlanHeaderProps) {\n return (\n <div\n data-slot=\"plan-header\"\n className={cn('flex min-h-10 items-center justify-between gap-3 px-4 pt-3', className)}\n {...props}\n >\n {children}\n </div>\n );\n}\n\nexport type PlanLabelProps = ComponentProps<'div'>;\n\nexport function PlanLabel({ children = 'Plan', className, ...props }: PlanLabelProps) {\n return (\n <div data-slot=\"plan-label\" className={cn('flex min-w-0 items-center gap-2', className)} {...props}>\n <Icon size=\"sm\" className=\"text-icon3\">\n <ClipboardList />\n </Icon>\n <Txt as=\"span\" variant=\"ui-sm\" className=\"text-neutral4\">\n {children}\n </Txt>\n </div>\n );\n}\n\nexport type PlanHeaderActionsProps = ComponentProps<'div'>;\n\nexport function PlanHeaderActions({ children, className, ...props }: PlanHeaderActionsProps) {\n return (\n <div data-slot=\"plan-header-actions\" className={cn('flex shrink-0 items-center gap-1', className)} {...props}>\n {children}\n </div>\n );\n}\n\nexport type PlanStatusProps = Omit<ComponentProps<typeof Badge>, 'icon' | 'size'>;\n\nexport function PlanStatus({ children, variant = 'default', ...props }: PlanStatusProps) {\n return (\n <Badge {...props} variant={variant} size=\"xs\" icon={<span className=\"size-1 rounded-full bg-current\" />}>\n {children}\n </Badge>\n );\n}\n\nexport interface PlanCopyButtonProps extends Omit<\n ComponentProps<typeof Button>,\n 'aria-label' | 'children' | 'onClick' | 'size' | 'tooltip' | 'type' | 'variant'\n> {\n content: string;\n}\n\nexport function PlanCopyButton({ content, ...props }: PlanCopyButtonProps) {\n const { isCopied, handleCopy } = useCopyToClipboard({\n text: content,\n copiedDuration: 1500,\n showToast: false,\n });\n\n return (\n <Button\n {...props}\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-sm\"\n tooltip=\"Copy plan\"\n aria-label=\"Copy plan\"\n onClick={handleCopy}\n >\n {isCopied ? <CheckIcon /> : <CopyIcon />}\n </Button>\n );\n}\n\nexport type PlanBodyProps = ComponentProps<'div'>;\n\nexport function PlanBody({ children, className, ...props }: PlanBodyProps) {\n return (\n <div data-slot=\"plan-body\" className={cn('px-5 pt-4 pb-5', className)} {...props}>\n {children}\n </div>\n );\n}\n\nexport type PlanIntroProps = ComponentProps<'div'>;\n\nexport function PlanIntro({ children, className, ...props }: PlanIntroProps) {\n return (\n <div data-slot=\"plan-intro\" className={cn('mb-5 space-y-1', className)} {...props}>\n {children}\n </div>\n );\n}\n\nexport interface PlanTitleProps extends Omit<ComponentProps<typeof Txt>, 'as' | 'children' | 'variant'> {\n children: ReactNode;\n}\n\nexport function PlanTitle({ children, className, ...props }: PlanTitleProps) {\n return (\n <Txt {...props} as=\"h3\" variant=\"header-sm\" className={cn('text-neutral7 font-semibold', className)}>\n {children}\n </Txt>\n );\n}\n\nexport interface PlanPathProps extends Omit<\n ComponentProps<typeof Txt>,\n 'as' | 'children' | 'font' | 'title' | 'variant'\n> {\n children: string;\n}\n\nconst getFileName = (path: string) => {\n const segments = path.split(/[\\\\/]/).filter(Boolean);\n return segments[segments.length - 1] ?? path;\n};\n\nexport function PlanPath({ children, className, ...props }: PlanPathProps) {\n return (\n <Txt\n {...props}\n as=\"p\"\n variant=\"ui-xs\"\n font=\"mono\"\n title={children}\n className={cn('max-w-full truncate overflow-hidden text-neutral3', className)}\n >\n {getFileName(children)}\n </Txt>\n );\n}\n\nexport type PlanMainProps = ComponentProps<'div'>;\n\nexport function PlanMain({ children, className, ...props }: PlanMainProps) {\n return (\n <div data-slot=\"plan-main\" className={cn('relative', className)} {...props}>\n {children}\n </div>\n );\n}\n\nexport interface PlanContentProps extends Omit<ComponentProps<'div'>, 'children'> {\n children: string;\n}\n\nexport function PlanContent({ children, className, style, ...props }: PlanContentProps) {\n const { collapsedHeight, isExpanded } = usePlanContext();\n\n return (\n <div\n data-slot=\"plan-content\"\n className={cn('relative', !isExpanded && 'overflow-hidden', className)}\n style={!isExpanded ? { ...style, maxHeight: collapsedHeight } : style}\n {...props}\n >\n <div className=\"[&_code]:bg-surface4 [&_h1]:text-header-md [&_h1]:leading-header-md [&_h2]:text-header-sm [&_h2]:leading-header-sm [&_h3]:text-ui-lg [&_h3]:leading-ui-lg [&_p]:text-ui-md [&_p]:leading-6\">\n <MarkdownRenderer className=\"text-neutral6\">{children}</MarkdownRenderer>\n </div>\n </div>\n );\n}\n\nexport interface PlanFileProps extends Omit<ComponentProps<'div'>, 'children'> {\n children: string;\n}\n\nexport function PlanFile({ children, className, ...props }: PlanFileProps) {\n return (\n <div data-slot=\"plan-file\" className={className} {...props}>\n <Txt as=\"p\" variant=\"ui-xs\" className=\"text-neutral3 mb-2\">\n Plan file\n </Txt>\n <Txt as=\"p\" variant=\"ui-sm\" className=\"text-neutral6 font-mono break-all\">\n {children}\n </Txt>\n </div>\n );\n}\n\nexport type PlanControlsProps = ComponentProps<'div'>;\n\nexport function PlanControls({ children, className, ...props }: PlanControlsProps) {\n const hasActions = Boolean(children);\n\n return (\n <div data-slot=\"plan-controls\" className={cn('relative z-10 mt-4 flex justify-center', className)} {...props}>\n {hasActions ? (\n <div className=\"grid w-full max-w-sm grid-cols-[1fr_auto_1fr] items-center gap-2 px-10\">{children}</div>\n ) : (\n <PlanExpandButton />\n )}\n </div>\n );\n}\n\nexport type PlanActionGroupProps = ComponentProps<'div'>;\n\nexport function PlanActionGroup({ children, className, ...props }: PlanActionGroupProps) {\n return (\n <div data-slot=\"plan-action-group\" className={cn('flex justify-start gap-2 empty:hidden', className)} {...props}>\n {children}\n </div>\n );\n}\n\nexport type PlanExpandButtonProps = Omit<\n ComponentProps<typeof Button>,\n 'aria-label' | 'children' | 'onClick' | 'size' | 'type' | 'variant'\n>;\n\nexport function PlanExpandButton({ className, ...props }: PlanExpandButtonProps) {\n const { isExpanded, toggleExpanded } = usePlanContext();\n\n return (\n <Button\n {...props}\n className={cn('shrink-0 whitespace-nowrap', className)}\n type=\"button\"\n variant=\"default\"\n size=\"sm\"\n aria-label={isExpanded ? 'Collapse plan' : 'Expand plan'}\n onClick={toggleExpanded}\n >\n {isExpanded ? <Minimize2 /> : <Maximize2 />}\n {isExpanded ? 'Collapse plan' : 'Expand plan'}\n </Button>\n );\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"plan.es.js","sources":["../../../src/ds/components/ai/plan/plan.tsx"],"sourcesContent":["import { CheckIcon, ClipboardList, CopyIcon, Maximize2, Minimize2 } from 'lucide-react';\nimport { createContext, useContext, useLayoutEffect, useRef, useState } from 'react';\nimport type { ComponentProps, ReactNode } from 'react';\n\nimport { Badge } from '@/ds/components/Badge';\nimport { Button } from '@/ds/components/Button';\nimport { MarkdownRenderer } from '@/ds/components/MarkdownRenderer';\nimport { Txt } from '@/ds/components/Txt';\nimport { Icon } from '@/ds/icons/Icon';\nimport { useCopyToClipboard } from '@/hooks/use-copy-to-clipboard';\nimport { cn } from '@/lib/utils';\n\nconst DEFAULT_COLLAPSED_HEIGHT = 220;\n\ninterface PlanContextValue {\n collapsedHeight: number;\n isExpanded: boolean;\n /** Whether the rendered content overflows the collapsed height (measured, not estimated). */\n isClipped: boolean;\n setClipped: (clipped: boolean) => void;\n toggleExpanded: () => void;\n}\n\nconst PlanContext = createContext<PlanContextValue | null>(null);\n\nconst usePlanContext = () => {\n const context = useContext(PlanContext);\n\n if (!context) {\n throw new Error('Plan compound components must be rendered inside <Plan>.');\n }\n\n return context;\n};\n\nexport interface PlanProps extends ComponentProps<'div'> {\n collapsedHeight?: number;\n}\n\nexport function Plan({ children, collapsedHeight = DEFAULT_COLLAPSED_HEIGHT, className, ...props }: PlanProps) {\n const [isExpanded, setIsExpanded] = useState(false);\n const [isClipped, setClipped] = useState(false);\n\n const toggleExpanded = () => {\n setIsExpanded(current => !current);\n };\n\n const contextValue = {\n collapsedHeight,\n isExpanded,\n isClipped,\n setClipped,\n toggleExpanded,\n };\n\n return (\n <PlanContext.Provider value={contextValue}>\n <div data-slot=\"plan\" className={cn('w-full overflow-hidden rounded-xl bg-surface3', className)} {...props}>\n {children}\n </div>\n </PlanContext.Provider>\n );\n}\n\nexport type PlanHeaderProps = ComponentProps<'div'>;\n\nexport function PlanHeader({ children, className, ...props }: PlanHeaderProps) {\n return (\n <div\n data-slot=\"plan-header\"\n className={cn('flex min-h-10 items-center justify-between gap-3 px-4 pt-3', className)}\n {...props}\n >\n {children}\n </div>\n );\n}\n\nexport type PlanLabelProps = ComponentProps<'div'>;\n\nexport function PlanLabel({ children = 'Plan', className, ...props }: PlanLabelProps) {\n return (\n <div data-slot=\"plan-label\" className={cn('flex min-w-0 items-center gap-2', className)} {...props}>\n <Icon size=\"sm\" className=\"text-icon3\">\n <ClipboardList />\n </Icon>\n <Txt as=\"span\" variant=\"ui-sm\" className=\"text-neutral4\">\n {children}\n </Txt>\n </div>\n );\n}\n\nexport type PlanHeaderActionsProps = ComponentProps<'div'>;\n\nexport function PlanHeaderActions({ children, className, ...props }: PlanHeaderActionsProps) {\n return (\n <div data-slot=\"plan-header-actions\" className={cn('flex shrink-0 items-center gap-1', className)} {...props}>\n {children}\n </div>\n );\n}\n\nexport type PlanStatusProps = Omit<ComponentProps<typeof Badge>, 'icon' | 'size'>;\n\nexport function PlanStatus({ children, variant = 'default', ...props }: PlanStatusProps) {\n return (\n <Badge {...props} variant={variant} size=\"xs\" icon={<span className=\"size-1 rounded-full bg-current\" />}>\n {children}\n </Badge>\n );\n}\n\nexport interface PlanCopyButtonProps extends Omit<\n ComponentProps<typeof Button>,\n 'aria-label' | 'children' | 'onClick' | 'size' | 'tooltip' | 'type' | 'variant'\n> {\n content: string;\n}\n\nexport function PlanCopyButton({ content, ...props }: PlanCopyButtonProps) {\n const { isCopied, handleCopy } = useCopyToClipboard({\n text: content,\n copiedDuration: 1500,\n showToast: false,\n });\n\n return (\n <Button\n {...props}\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-sm\"\n tooltip=\"Copy plan\"\n aria-label=\"Copy plan\"\n onClick={handleCopy}\n >\n {isCopied ? <CheckIcon /> : <CopyIcon />}\n </Button>\n );\n}\n\nexport type PlanBodyProps = ComponentProps<'div'>;\n\nexport function PlanBody({ children, className, ...props }: PlanBodyProps) {\n return (\n <div data-slot=\"plan-body\" className={cn('px-5 pt-4 pb-5', className)} {...props}>\n {children}\n </div>\n );\n}\n\nexport type PlanIntroProps = ComponentProps<'div'>;\n\nexport function PlanIntro({ children, className, ...props }: PlanIntroProps) {\n return (\n <div data-slot=\"plan-intro\" className={cn('mb-5 space-y-1', className)} {...props}>\n {children}\n </div>\n );\n}\n\nexport interface PlanTitleProps extends Omit<ComponentProps<typeof Txt>, 'as' | 'children' | 'variant'> {\n children: ReactNode;\n}\n\nexport function PlanTitle({ children, className, ...props }: PlanTitleProps) {\n return (\n <Txt {...props} as=\"h3\" variant=\"header-sm\" className={cn('text-neutral7 font-semibold', className)}>\n {children}\n </Txt>\n );\n}\n\nexport interface PlanPathProps extends Omit<\n ComponentProps<typeof Txt>,\n 'as' | 'children' | 'font' | 'title' | 'variant'\n> {\n children: string;\n}\n\nconst getFileName = (path: string) => {\n const segments = path.split(/[\\\\/]/).filter(Boolean);\n return segments[segments.length - 1] ?? path;\n};\n\nexport function PlanPath({ children, className, ...props }: PlanPathProps) {\n return (\n <Txt\n {...props}\n as=\"p\"\n variant=\"ui-xs\"\n font=\"mono\"\n title={children}\n className={cn('max-w-full truncate overflow-hidden text-neutral3', className)}\n >\n {getFileName(children)}\n </Txt>\n );\n}\n\nexport type PlanMainProps = ComponentProps<'div'>;\n\nexport function PlanMain({ children, className, ...props }: PlanMainProps) {\n return (\n <div data-slot=\"plan-main\" className={cn('relative', className)} {...props}>\n {children}\n </div>\n );\n}\n\nexport interface PlanContentProps extends Omit<ComponentProps<'div'>, 'children'> {\n children: string;\n}\n\nexport function PlanContent({ children, className, style, ...props }: PlanContentProps) {\n const { collapsedHeight, isExpanded, isClipped, setClipped } = usePlanContext();\n const contentRef = useRef<HTMLDivElement>(null);\n\n // Measure the rendered content against the collapsed height so the clip hint\n // and expand control track actual overflow — not an estimate of it.\n useLayoutEffect(() => {\n const element = contentRef.current;\n if (!element) return;\n\n const measure = () => setClipped(element.scrollHeight > collapsedHeight);\n measure();\n\n if (typeof ResizeObserver === 'undefined') return;\n const observer = new ResizeObserver(measure);\n observer.observe(element);\n return () => observer.disconnect();\n }, [children, collapsedHeight, setClipped]);\n\n const showClipHint = !isExpanded && isClipped;\n\n return (\n <div\n data-slot=\"plan-content\"\n // The clip hint masks the content itself, so it reads correctly on any card background.\n {...(showClipHint ? { 'data-clipped': '' } : {})}\n className={cn(\n 'relative',\n !isExpanded && 'overflow-hidden',\n showClipHint && 'mask-b-from-60% mask-b-to-100%',\n className,\n )}\n style={!isExpanded ? { ...style, maxHeight: collapsedHeight } : style}\n {...props}\n >\n <div\n ref={contentRef}\n className=\"[&_code]:bg-surface4 [&_h1]:text-header-md [&_h1]:leading-header-md [&_h2]:text-header-sm [&_h2]:leading-header-sm [&_h3]:text-ui-lg [&_h3]:leading-ui-lg [&_p]:text-ui-md [&_p]:leading-6\"\n >\n <MarkdownRenderer className=\"text-neutral6\">{children}</MarkdownRenderer>\n </div>\n </div>\n );\n}\n\nexport interface PlanFileProps extends Omit<ComponentProps<'div'>, 'children'> {\n children: string;\n}\n\nexport function PlanFile({ children, className, ...props }: PlanFileProps) {\n return (\n <div data-slot=\"plan-file\" className={className} {...props}>\n <Txt as=\"p\" variant=\"ui-xs\" className=\"text-neutral3 mb-2\">\n Plan file\n </Txt>\n <Txt as=\"p\" variant=\"ui-sm\" className=\"text-neutral6 font-mono break-all\">\n {children}\n </Txt>\n </div>\n );\n}\n\nexport type PlanControlsProps = ComponentProps<'div'>;\n\nexport function PlanControls({ children, className, ...props }: PlanControlsProps) {\n const hasActions = Boolean(children);\n\n return (\n <div\n data-slot=\"plan-controls\"\n className={cn('relative z-10 mt-4 flex justify-center empty:hidden', className)}\n {...props}\n >\n {hasActions ? (\n <div className=\"grid w-full max-w-sm grid-cols-[1fr_auto_1fr] items-center gap-2 px-10\">{children}</div>\n ) : (\n <PlanExpandButton />\n )}\n </div>\n );\n}\n\nexport type PlanActionGroupProps = ComponentProps<'div'>;\n\nexport function PlanActionGroup({ children, className, ...props }: PlanActionGroupProps) {\n return (\n <div data-slot=\"plan-action-group\" className={cn('flex justify-start gap-2 empty:hidden', className)} {...props}>\n {children}\n </div>\n );\n}\n\nexport type PlanExpandButtonProps = Omit<\n ComponentProps<typeof Button>,\n 'aria-label' | 'children' | 'onClick' | 'size' | 'type' | 'variant'\n>;\n\nexport function PlanExpandButton({ className, ...props }: PlanExpandButtonProps) {\n const { isExpanded, isClipped, toggleExpanded } = usePlanContext();\n\n // Nothing to expand: the collapsed card already shows the whole plan.\n if (!isClipped && !isExpanded) return null;\n\n return (\n <Button\n {...props}\n className={cn('shrink-0 whitespace-nowrap', className)}\n type=\"button\"\n variant=\"default\"\n size=\"sm\"\n aria-label={isExpanded ? 'Collapse plan' : 'Expand plan'}\n onClick={toggleExpanded}\n >\n {isExpanded ? <Minimize2 /> : <Maximize2 />}\n {isExpanded ? 'Collapse plan' : 'Expand plan'}\n </Button>\n );\n}\n"],"names":[],"mappings":"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"}
@@ -44,6 +44,8 @@ function SankeySignals({
44
44
  dateFrom,
45
45
  dateTo,
46
46
  height,
47
+ selectedThemeId,
48
+ onSelectedThemeIdChange,
47
49
  dateRangePicker
48
50
  }) {
49
51
  const queryClient = reactQuery.useQueryClient();
@@ -56,7 +58,6 @@ function SankeySignals({
56
58
  const [isPlaying, setIsPlaying] = React.useState(false);
57
59
  const [viewMode, setViewMode] = React.useState("flow");
58
60
  const [drillStack, setDrillStack] = React.useState([]);
59
- const [detailSelection, setDetailSelection] = React.useState();
60
61
  const [noiseSignalName, setNoiseSignalName] = React.useState();
61
62
  const matchedSnapshotIndex = snapshots.findIndex((snapshot2) => snapshot2.ordinal === selectedSnapshotOrdinal);
62
63
  const selectedSnapshotIndex = matchedSnapshotIndex >= 0 ? matchedSnapshotIndex : 0;
@@ -71,11 +72,14 @@ function SankeySignals({
71
72
  if (nextIsPlaying && selectedSnapshotIndex === snapshots.length - 1) selectSnapshot(0);
72
73
  setIsPlaying(nextIsPlaying);
73
74
  };
75
+ const setThemeDetails = (selection) => {
76
+ onSelectedThemeIdChange(selection?.themeId);
77
+ };
74
78
  const openThemeDetailsAt = (selection, snapshotIndex) => {
75
79
  if (selection.kind !== "theme") return;
76
80
  selectSnapshot(snapshotIndex);
77
81
  setNoiseSignalName(void 0);
78
- setDetailSelection(selection);
82
+ setThemeDetails(selection);
79
83
  };
80
84
  const nextSnapshotOrdinal = snapshots[selectedSnapshotIndex + 1]?.ordinal;
81
85
  const flowSnapshotIds = ee_signals_sankeySignalsData.selectFlowSnapshotIds(snapshots, selectedSnapshotIndex);
@@ -104,6 +108,7 @@ function SankeySignals({
104
108
  return ee_signals_sankeySignalsData.stabilizeThemeFlow(drilledFlow, [stableUnfilteredFlow, drilledFlow]);
105
109
  }, [drillStack, pathsQuery.data, stableUnfilteredFlow]);
106
110
  const graphSummary = React.useMemo(() => flow ? ee_signals_sankeySignalsData.buildSignalGraphSummary(flow) : void 0, [flow]);
111
+ const detailSelection = stableUnfilteredFlow && selectedThemeId ? ee_signals_themeDrilldownData.findThemeSelectionById(stableUnfilteredFlow, selectedThemeId) : void 0;
107
112
  const populatedStageCount = currentFlow?.stages.filter((stage) => stage.nodes.length > 0).length ?? 0;
108
113
  const shouldLoadProgress = snapshotsQuery.isSuccess && !snapshotsQuery.isError && (!snapshot || Boolean(currentFlow && (!flow || !graphSummary || populatedStageCount < 2)));
109
114
  const progressQuery = ee_signals_hooks_useEntityLearningProgress.useEntityLearningProgress(entityId, entityType, shouldLoadProgress);
@@ -232,10 +237,10 @@ function SankeySignals({
232
237
  if (!nextSelection || drillStack.some((filter) => filter.signalName === nextSelection.signalName)) return;
233
238
  if (nextSelection.kind === "theme") {
234
239
  setNoiseSignalName(void 0);
235
- setDetailSelection(nextSelection);
240
+ setThemeDetails(nextSelection);
236
241
  if (drillInAvailable) setDrillStack((current) => [...current, nextSelection]);
237
242
  } else {
238
- setDetailSelection(void 0);
243
+ setThemeDetails(void 0);
239
244
  setNoiseSignalName(nextSelection.signalName);
240
245
  }
241
246
  };
@@ -244,7 +249,7 @@ function SankeySignals({
244
249
  const handleSignalOrderChange = (nextSignalNames) => {
245
250
  if (perspectiveMutation.isPending) return;
246
251
  setIsPlaying(false);
247
- setDetailSelection(void 0);
252
+ setThemeDetails(void 0);
248
253
  setNoiseSignalName(void 0);
249
254
  const mergedSignalNames = ee_signals_themeDrilldownData.mergeVisibleSignalOrder(signalNames, nextSignalNames);
250
255
  setPendingSignalNames(mergedSignalNames);
@@ -321,9 +326,9 @@ function SankeySignals({
321
326
  onViewDetails: (selection) => {
322
327
  if (selection.kind === "theme") {
323
328
  setNoiseSignalName(void 0);
324
- setDetailSelection(selection);
329
+ setThemeDetails(selection);
325
330
  } else {
326
- setDetailSelection(void 0);
331
+ setThemeDetails(void 0);
327
332
  setNoiseSignalName(selection.signalName);
328
333
  }
329
334
  },
@@ -359,7 +364,7 @@ function SankeySignals({
359
364
  selection: detailSelection,
360
365
  filters: drillStack,
361
366
  filteredStats: detailStats,
362
- onClose: () => setDetailSelection(void 0)
367
+ onClose: () => setThemeDetails(void 0)
363
368
  },
364
369
  `${snapshot.snapshotId}:${detailSelection?.signalName ?? ""}:${detailSelection?.themeId ?? ""}:${filterKey}`
365
370
  ),