@tetrascience-npm/tetrascience-react-ui 1.0.0-beta.155.1 → 1.0.0-beta.156.1

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.
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const s=require("react/jsx-runtime"),j=require("lucide-react"),k=require("react"),p=require("./dockLayout.cjs"),D=require("../../../ui/button.cjs"),x=require("../../../ui/resizable.cjs"),u=require("../../../lib/utils.cjs");function L(n){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(n){for(const e in n)if(e!=="default"){const o=Object.getOwnPropertyDescriptor(n,e);Object.defineProperty(t,e,o.get?o:{enumerable:!0,get:()=>n[e]})}}return t.default=n,Object.freeze(t)}const l=L(k),N=l.createContext(null);function I(n,t){if(typeof window>"u")return t;const e=window.localStorage.getItem(`${n}.dock`);return e==="right"||e==="bottom"||e==="left"?e:t}function C(n,t){if(typeof window>"u")return t;const e=Number(window.localStorage.getItem(`${n}.size`));return!Number.isFinite(e)||e<=0||e>=100?t:e}function R({children:n,storageKey:t="ts-ui.assistant",defaultDock:e="left",defaultSize:o=32,defaultVisible:f=!0,persist:i=!0}){const[a,c]=l.useState(()=>i?I(t,e):e),[m,r]=l.useState(()=>i?C(t,o):o),[h,S]=l.useState(f),w=l.useCallback(d=>{c(d),i&&typeof window<"u"&&window.localStorage.setItem(`${t}.dock`,d)},[t,i]),b=l.useCallback(d=>{r(d),i&&typeof window<"u"&&window.localStorage.setItem(`${t}.size`,String(Math.round(d)))},[t,i]),v=l.useMemo(()=>({dock:a,setDock:w,size:m,setSize:b,visible:h,setVisible:S}),[a,w,m,b,h]);return s.jsx(N.Provider,{value:v,children:n})}function y(){const n=l.useContext(N);if(!n)throw new Error("useAssistantLayout must be used within an AssistantLayoutProvider");return n}const _=[{value:"left",label:"Dock assistant left",Icon:j.PanelLeft},{value:"bottom",label:"Dock assistant bottom",Icon:j.PanelBottom},{value:"right",label:"Dock assistant right",Icon:j.PanelRight}];function O({label:n="AI Assistant",className:t}){const{dock:e,setDock:o,visible:f,setVisible:i}=y();return s.jsxs("div",{className:u.cn("flex items-center gap-2",t),children:[n!=null&&s.jsx("span",{className:"text-sm font-medium",children:n}),s.jsx("div",{className:"inline-flex overflow-hidden rounded-lg border border-border",children:_.map(({value:a,label:c,Icon:m})=>{const r=f&&e===a;return s.jsx(D.Button,{variant:r?"secondary":"ghost",size:"icon-sm",className:"rounded-none bg-clip-border","aria-label":r?"Hide AI Assistant":c,"aria-pressed":r,title:r?"Hide AI Assistant":c,onClick:()=>{r?i(!1):(o(a),i(!0))},children:s.jsx(m,{className:"size-4"})},a)})})]})}const A="flex min-h-0 min-w-0 p-2",g="flex h-full min-h-0 min-w-0 flex-1 flex-col overflow-hidden rounded-lg border border-border bg-card",z="assistant";function q({assistant:n,children:t,minSize:e=20,maxSize:o=70,className:f,assistantClassName:i,contentClassName:a}){const{dock:c,size:m,setSize:r,visible:h}=y(),{orientation:S,assistantFirst:w}=p.dockPanels(c);if(!h)return s.jsx("div",{"data-slot":"assistant-layout",className:u.cn("flex min-h-0 flex-1 overflow-hidden",f),children:s.jsx("div",{className:u.cn(A,"flex-1"),children:s.jsx("div",{"data-slot":"assistant-layout-content",className:u.cn(g,a),children:t})})});const b=s.jsx(x.ResizablePanel,{id:z,defaultSize:`${m}%`,minSize:`${e}%`,maxSize:`${o}%`,className:A,children:s.jsx("div",{"data-slot":"assistant-layout-assistant",className:u.cn(g,i),children:n})}),v=s.jsx(x.ResizablePanel,{id:"content",className:A,children:s.jsx("div",{"data-slot":"assistant-layout-content",className:u.cn(g,a),children:t})});return s.jsx(x.ResizablePanelGroup,{orientation:S,"data-slot":"assistant-layout",className:u.cn("min-h-0 flex-1 overflow-hidden",f),onLayoutChanged:d=>{const P=d[z];typeof P=="number"&&r(P)},children:w?s.jsxs(s.Fragment,{children:[b,s.jsx(x.ResizableHandle,{withHandle:!0}),v]}):s.jsxs(s.Fragment,{children:[v,s.jsx(x.ResizableHandle,{withHandle:!0}),b]})},c)}exports.AssistantDockControls=O;exports.AssistantLayout=q;exports.AssistantLayoutProvider=R;exports.useAssistantLayout=y;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),v=require("lucide-react"),O=require("react"),H=require("./dockLayout.cjs"),P=require("../../../ui/button.cjs"),x=require("../../../ui/resizable.cjs"),u=require("../../../lib/utils.cjs");function q(n){const s=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(n){for(const t in n)if(t!=="default"){const i=Object.getOwnPropertyDescriptor(n,t);Object.defineProperty(s,t,i.get?i:{enumerable:!0,get:()=>n[t]})}}return s.default=n,Object.freeze(s)}const l=q(O),D=l.createContext(null);function $(n,s){if(typeof window>"u")return s;const t=window.localStorage.getItem(`${n}.dock`);return t==="right"||t==="bottom"||t==="left"?t:s}function F(n,s){if(typeof window>"u")return s;const t=Number(window.localStorage.getItem(`${n}.size`));return!Number.isFinite(t)||t<=0||t>=100?s:t}function M({children:n,storageKey:s="ts-ui.assistant",defaultDock:t="left",defaultSize:i=32,defaultVisible:m=!0,persist:a=!0}){const[r,f]=l.useState(()=>a?$(s,t):t),[c,o]=l.useState(()=>a?F(s,i):i),[b,h]=l.useState(m),j=l.useCallback(d=>{f(d),a&&typeof window<"u"&&window.localStorage.setItem(`${s}.dock`,d)},[s,a]),w=l.useCallback(d=>{o(d),a&&typeof window<"u"&&window.localStorage.setItem(`${s}.size`,String(Math.round(d)))},[s,a]),g=l.useMemo(()=>({dock:r,setDock:j,size:c,setSize:w,visible:b,setVisible:h}),[r,j,c,w,b]);return e.jsx(D.Provider,{value:g,children:n})}function A(){const n=l.useContext(D);if(!n)throw new Error("useAssistantLayout must be used within an AssistantLayoutProvider");return n}const B=[{value:"left",label:"Dock assistant left",Icon:v.PanelLeft},{value:"bottom",label:"Dock assistant bottom",Icon:v.PanelBottom},{value:"right",label:"Dock assistant right",Icon:v.PanelRight}];function E({label:n="AI Assistant",className:s}){const{dock:t,setDock:i,visible:m,setVisible:a}=A();return e.jsxs("div",{className:u.cn("flex items-center gap-2",s),children:[n!=null&&e.jsx("span",{className:"text-sm font-medium",children:n}),e.jsx("div",{className:"inline-flex overflow-hidden rounded-lg border border-border",children:B.map(({value:r,label:f,Icon:c})=>{const o=m&&t===r;return e.jsx(P.Button,{variant:o?"secondary":"ghost",size:"icon-sm",className:"rounded-none bg-clip-border","aria-label":o?"Hide AI Assistant":f,"aria-pressed":o,title:o?"Hide AI Assistant":f,onClick:()=>{o?a(!1):(i(r),a(!0))},children:e.jsx(c,{className:"size-4"})},r)})})]})}const y="flex min-h-0 min-w-0 p-2",S="flex h-full min-h-0 min-w-0 flex-1 flex-col overflow-hidden rounded-lg border border-border bg-card",z="assistant";function T({assistant:n,children:s,assistantTitle:t,assistantIcon:i,assistantHeaderActions:m,showAssistantClose:a,minSize:r=20,maxSize:f=70,className:c,assistantClassName:o,contentClassName:b}){const{dock:h,size:j,setSize:w,visible:g,setVisible:d}=A(),{orientation:L,assistantFirst:C}=H.dockPanels(h),I=a??t!=null,R=t!=null&&e.jsxs("div",{"data-slot":"assistant-layout-assistant-header",className:"flex shrink-0 items-center gap-2 border-b border-primary/15 bg-accent px-3 py-2",children:[i!=null&&e.jsx("span",{className:"flex shrink-0 items-center justify-center",children:i}),e.jsx("span",{className:"min-w-0 flex-1 truncate text-sm font-semibold text-foreground",children:t}),m,I&&e.jsx(P.Button,{variant:"ghost",size:"icon-sm",className:"text-muted-foreground","aria-label":"Hide assistant",onClick:()=>d(!1),children:e.jsx(v.X,{})})]});if(!g)return e.jsx("div",{"data-slot":"assistant-layout",className:u.cn("flex min-h-0 flex-1 overflow-hidden",c),children:e.jsx("div",{className:u.cn(y,"flex-1"),children:e.jsx("div",{"data-slot":"assistant-layout-content",className:u.cn(S,b),children:s})})});const N=e.jsx(x.ResizablePanel,{id:z,defaultSize:`${j}%`,minSize:`${r}%`,maxSize:`${f}%`,className:y,children:e.jsxs("div",{"data-slot":"assistant-layout-assistant",className:u.cn(S,o),children:[R,n]})}),k=e.jsx(x.ResizablePanel,{id:"content",className:y,children:e.jsx("div",{"data-slot":"assistant-layout-content",className:u.cn(S,b),children:s})});return e.jsx(x.ResizablePanelGroup,{orientation:L,"data-slot":"assistant-layout",className:u.cn("min-h-0 flex-1 overflow-hidden",c),onLayoutChanged:_=>{const p=_[z];typeof p=="number"&&w(p)},children:C?e.jsxs(e.Fragment,{children:[N,e.jsx(x.ResizableHandle,{withHandle:!0}),k]}):e.jsxs(e.Fragment,{children:[k,e.jsx(x.ResizableHandle,{withHandle:!0}),N]})},h)}exports.AssistantDockControls=E;exports.AssistantLayout=T;exports.AssistantLayoutProvider=M;exports.useAssistantLayout=A;
2
2
  //# sourceMappingURL=AssistantLayout.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"AssistantLayout.cjs","sources":["../../../../src/components/composed/AssistantLayout/AssistantLayout.tsx"],"sourcesContent":["\"use client\"\n\nimport { PanelBottom, PanelLeft, PanelRight } from \"lucide-react\"\nimport * as React from \"react\"\n\nimport { dockPanels, type AssistantDock } from \"./dockLayout\"\n\nimport { Button } from \"@/components/ui/button\"\nimport {\n ResizableHandle,\n ResizablePanel,\n ResizablePanelGroup,\n} from \"@/components/ui/resizable\"\nimport { cn } from \"@/lib/utils\"\n\n// ---------------------------------------------------------------------------\n// Context + provider\n// ---------------------------------------------------------------------------\n\ninterface AssistantLayoutContextValue {\n /** Where the assistant docks. Persisted. */\n dock: AssistantDock\n setDock: (dock: AssistantDock) => void\n /** Assistant size as a percentage of the layout along the dock axis. Persisted. */\n size: number\n setSize: (size: number) => void\n /** Whether the assistant is shown. In-memory by default (resets to visible on reload). */\n visible: boolean\n setVisible: (visible: boolean) => void\n}\n\nconst AssistantLayoutContext = React.createContext<AssistantLayoutContextValue | null>(null)\n\nexport interface AssistantLayoutProviderProps {\n children: React.ReactNode\n /** localStorage key prefix for the persisted dock + size. */\n storageKey?: string\n /** Default dock when nothing is persisted. */\n defaultDock?: AssistantDock\n /** Default assistant size as a percentage (1–99) of the layout. */\n defaultSize?: number\n /** Whether the assistant starts visible. */\n defaultVisible?: boolean\n /** Persist dock + size to localStorage. Defaults to `true`. */\n persist?: boolean\n}\n\nfunction readDock(key: string, fallback: AssistantDock): AssistantDock {\n if (typeof window === \"undefined\") return fallback\n const v = window.localStorage.getItem(`${key}.dock`)\n return v === \"right\" || v === \"bottom\" || v === \"left\" ? v : fallback\n}\n\nfunction readSize(key: string, fallback: number): number {\n if (typeof window === \"undefined\") return fallback\n const v = Number(window.localStorage.getItem(`${key}.size`))\n // Persisted as a percentage; ignore anything outside the open (0, 100) range.\n if (!Number.isFinite(v) || v <= 0 || v >= 100) return fallback\n return v\n}\n\nexport function AssistantLayoutProvider({\n children,\n storageKey = \"ts-ui.assistant\",\n defaultDock = \"left\",\n defaultSize = 32,\n defaultVisible = true,\n persist = true,\n}: AssistantLayoutProviderProps) {\n const [dock, setDockState] = React.useState<AssistantDock>(() =>\n persist ? readDock(storageKey, defaultDock) : defaultDock\n )\n const [size, setSizeState] = React.useState<number>(() =>\n persist ? readSize(storageKey, defaultSize) : defaultSize\n )\n const [visible, setVisible] = React.useState(defaultVisible)\n\n const setDock = React.useCallback(\n (next: AssistantDock) => {\n setDockState(next)\n if (persist && typeof window !== \"undefined\")\n window.localStorage.setItem(`${storageKey}.dock`, next)\n },\n [storageKey, persist]\n )\n\n const setSize = React.useCallback(\n (next: number) => {\n setSizeState(next)\n if (persist && typeof window !== \"undefined\")\n window.localStorage.setItem(`${storageKey}.size`, String(Math.round(next)))\n },\n [storageKey, persist]\n )\n\n const value = React.useMemo(\n () => ({ dock, setDock, size, setSize, visible, setVisible }),\n [dock, setDock, size, setSize, visible]\n )\n\n return <AssistantLayoutContext.Provider value={value}>{children}</AssistantLayoutContext.Provider>\n}\n\nexport function useAssistantLayout(): AssistantLayoutContextValue {\n const ctx = React.useContext(AssistantLayoutContext)\n if (!ctx) throw new Error(\"useAssistantLayout must be used within an AssistantLayoutProvider\")\n return ctx\n}\n\n// ---------------------------------------------------------------------------\n// Dock controls (segmented icon control for a top bar)\n// ---------------------------------------------------------------------------\n\nconst DOCK_OPTIONS: { value: AssistantDock; label: string; Icon: typeof PanelLeft }[] = [\n { value: \"left\", label: \"Dock assistant left\", Icon: PanelLeft },\n { value: \"bottom\", label: \"Dock assistant bottom\", Icon: PanelBottom },\n { value: \"right\", label: \"Dock assistant right\", Icon: PanelRight },\n]\n\nexport interface AssistantDockControlsProps {\n /** Label shown before the icons. Pass `null` to hide it. */\n label?: React.ReactNode\n className?: string\n}\n\n/**\n * Segmented control of dock icons. Clicking an inactive icon docks + shows the\n * assistant there; clicking the active icon again hides it.\n */\nexport function AssistantDockControls({ label = \"AI Assistant\", className }: AssistantDockControlsProps) {\n const { dock, setDock, visible, setVisible } = useAssistantLayout()\n\n return (\n <div className={cn(\"flex items-center gap-2\", className)}>\n {label != null && <span className=\"text-sm font-medium\">{label}</span>}\n <div className=\"inline-flex overflow-hidden rounded-lg border border-border\">\n {DOCK_OPTIONS.map(({ value, label: optionLabel, Icon }) => {\n const active = visible && dock === value\n return (\n <Button\n key={value}\n variant={active ? \"secondary\" : \"ghost\"}\n size=\"icon-sm\"\n // bg-clip-border so the filled (active/hover) state reaches the\n // cell edge instead of leaving a 1px gap from the button's\n // transparent border + default bg-clip-padding.\n className=\"rounded-none bg-clip-border\"\n aria-label={active ? \"Hide AI Assistant\" : optionLabel}\n aria-pressed={active}\n title={active ? \"Hide AI Assistant\" : optionLabel}\n onClick={() => {\n if (active) setVisible(false)\n else {\n setDock(value)\n setVisible(true)\n }\n }}\n >\n <Icon className=\"size-4\" />\n </Button>\n )\n })}\n </div>\n </div>\n )\n}\n\n// ---------------------------------------------------------------------------\n// Layout body\n// ---------------------------------------------------------------------------\n\n// Each panel is padded so the resize handle sits in a comfortable gutter between\n// the cards rather than a hairline seam (SW-2096). The padding lives inside the\n// panel box, so react-resizable-panels' flex sizing is unaffected.\nconst PANEL_PAD = \"flex min-h-0 min-w-0 p-2\"\n// The visible card surface rendered inside each panel.\nconst CARD_CLASS =\n \"flex h-full min-h-0 min-w-0 flex-1 flex-col overflow-hidden rounded-lg border border-border bg-card\"\n\nconst ASSISTANT_PANEL_ID = \"assistant\"\n\nexport interface AssistantLayoutProps {\n /** The AI Assistant panel content (e.g. a `<Chat />`). */\n assistant: React.ReactNode\n /** The main content; fills the remaining space (and the whole body when the assistant is hidden). */\n children: React.ReactNode\n /** Min assistant size as a percentage of the layout. */\n minSize?: number\n /** Max assistant size as a percentage of the layout. */\n maxSize?: number\n className?: string\n assistantClassName?: string\n contentClassName?: string\n}\n\n/**\n * Docks the assistant left / right / bottom of the main content and resizes it\n * with the design-system `Resizable` (react-resizable-panels). Must be rendered\n * inside an `AssistantLayoutProvider`; pair with `AssistantDockControls`.\n *\n * The group is keyed by `dock`, so changing dock remounts the panels. The\n * assistant panel is therefore re-created on redock (its transient state is not\n * preserved across a dock change) — a deliberate trade-off for using the shared\n * resizable primitive rather than a bespoke splitter.\n */\nexport function AssistantLayout({\n assistant,\n children,\n minSize = 20,\n maxSize = 70,\n className,\n assistantClassName,\n contentClassName,\n}: AssistantLayoutProps) {\n const { dock, size, setSize, visible } = useAssistantLayout()\n const { orientation, assistantFirst } = dockPanels(dock)\n\n // Hidden: no resizable group, content fills the whole body.\n if (!visible) {\n return (\n <div\n data-slot=\"assistant-layout\"\n className={cn(\"flex min-h-0 flex-1 overflow-hidden\", className)}\n >\n {/* flex-1 so the lone content panel fills the width (the ResizablePanel\n self-sizes when visible; this plain div needs to be told to grow).\n Padded to match the inset the visible panels carry. */}\n <div className={cn(PANEL_PAD, \"flex-1\")}>\n <div data-slot=\"assistant-layout-content\" className={cn(CARD_CLASS, contentClassName)}>\n {children}\n </div>\n </div>\n </div>\n )\n }\n\n const assistantPanel = (\n <ResizablePanel\n id={ASSISTANT_PANEL_ID}\n defaultSize={`${size}%`}\n minSize={`${minSize}%`}\n maxSize={`${maxSize}%`}\n className={PANEL_PAD}\n >\n <div data-slot=\"assistant-layout-assistant\" className={cn(CARD_CLASS, assistantClassName)}>\n {assistant}\n </div>\n </ResizablePanel>\n )\n\n const contentPanel = (\n <ResizablePanel id=\"content\" className={PANEL_PAD}>\n <div data-slot=\"assistant-layout-content\" className={cn(CARD_CLASS, contentClassName)}>\n {children}\n </div>\n </ResizablePanel>\n )\n\n return (\n <ResizablePanelGroup\n key={dock}\n orientation={orientation}\n data-slot=\"assistant-layout\"\n className={cn(\"min-h-0 flex-1 overflow-hidden\", className)}\n onLayoutChanged={(layout) => {\n const pct = layout[ASSISTANT_PANEL_ID]\n if (typeof pct === \"number\") setSize(pct)\n }}\n >\n {assistantFirst ? (\n <>\n {assistantPanel}\n <ResizableHandle withHandle />\n {contentPanel}\n </>\n ) : (\n <>\n {contentPanel}\n <ResizableHandle withHandle />\n {assistantPanel}\n </>\n )}\n </ResizablePanelGroup>\n )\n}\n"],"names":["AssistantLayoutContext","React","readDock","key","fallback","v","readSize","AssistantLayoutProvider","children","storageKey","defaultDock","defaultSize","defaultVisible","persist","dock","setDockState","size","setSizeState","visible","setVisible","setDock","next","setSize","value","jsx","useAssistantLayout","ctx","DOCK_OPTIONS","PanelLeft","PanelBottom","PanelRight","AssistantDockControls","label","className","cn","optionLabel","Icon","active","Button","PANEL_PAD","CARD_CLASS","ASSISTANT_PANEL_ID","AssistantLayout","assistant","minSize","maxSize","assistantClassName","contentClassName","orientation","assistantFirst","dockPanels","assistantPanel","ResizablePanel","contentPanel","ResizablePanelGroup","layout","pct","jsxs","Fragment","ResizableHandle"],"mappings":"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"}
1
+ {"version":3,"file":"AssistantLayout.cjs","sources":["../../../../src/components/composed/AssistantLayout/AssistantLayout.tsx"],"sourcesContent":["\"use client\"\n\nimport { PanelBottom, PanelLeft, PanelRight, X } from \"lucide-react\"\nimport * as React from \"react\"\n\nimport { dockPanels, type AssistantDock } from \"./dockLayout\"\n\nimport { Button } from \"@/components/ui/button\"\nimport {\n ResizableHandle,\n ResizablePanel,\n ResizablePanelGroup,\n} from \"@/components/ui/resizable\"\nimport { cn } from \"@/lib/utils\"\n\n// ---------------------------------------------------------------------------\n// Context + provider\n// ---------------------------------------------------------------------------\n\ninterface AssistantLayoutContextValue {\n /** Where the assistant docks. Persisted. */\n dock: AssistantDock\n setDock: (dock: AssistantDock) => void\n /** Assistant size as a percentage of the layout along the dock axis. Persisted. */\n size: number\n setSize: (size: number) => void\n /** Whether the assistant is shown. In-memory by default (resets to visible on reload). */\n visible: boolean\n setVisible: (visible: boolean) => void\n}\n\nconst AssistantLayoutContext = React.createContext<AssistantLayoutContextValue | null>(null)\n\nexport interface AssistantLayoutProviderProps {\n children: React.ReactNode\n /** localStorage key prefix for the persisted dock + size. */\n storageKey?: string\n /** Default dock when nothing is persisted. */\n defaultDock?: AssistantDock\n /** Default assistant size as a percentage (1–99) of the layout. */\n defaultSize?: number\n /** Whether the assistant starts visible. */\n defaultVisible?: boolean\n /** Persist dock + size to localStorage. Defaults to `true`. */\n persist?: boolean\n}\n\nfunction readDock(key: string, fallback: AssistantDock): AssistantDock {\n if (typeof window === \"undefined\") return fallback\n const v = window.localStorage.getItem(`${key}.dock`)\n return v === \"right\" || v === \"bottom\" || v === \"left\" ? v : fallback\n}\n\nfunction readSize(key: string, fallback: number): number {\n if (typeof window === \"undefined\") return fallback\n const v = Number(window.localStorage.getItem(`${key}.size`))\n // Persisted as a percentage; ignore anything outside the open (0, 100) range.\n if (!Number.isFinite(v) || v <= 0 || v >= 100) return fallback\n return v\n}\n\nexport function AssistantLayoutProvider({\n children,\n storageKey = \"ts-ui.assistant\",\n defaultDock = \"left\",\n defaultSize = 32,\n defaultVisible = true,\n persist = true,\n}: AssistantLayoutProviderProps) {\n const [dock, setDockState] = React.useState<AssistantDock>(() =>\n persist ? readDock(storageKey, defaultDock) : defaultDock\n )\n const [size, setSizeState] = React.useState<number>(() =>\n persist ? readSize(storageKey, defaultSize) : defaultSize\n )\n const [visible, setVisible] = React.useState(defaultVisible)\n\n const setDock = React.useCallback(\n (next: AssistantDock) => {\n setDockState(next)\n if (persist && typeof window !== \"undefined\")\n window.localStorage.setItem(`${storageKey}.dock`, next)\n },\n [storageKey, persist]\n )\n\n const setSize = React.useCallback(\n (next: number) => {\n setSizeState(next)\n if (persist && typeof window !== \"undefined\")\n window.localStorage.setItem(`${storageKey}.size`, String(Math.round(next)))\n },\n [storageKey, persist]\n )\n\n const value = React.useMemo(\n () => ({ dock, setDock, size, setSize, visible, setVisible }),\n [dock, setDock, size, setSize, visible]\n )\n\n return <AssistantLayoutContext.Provider value={value}>{children}</AssistantLayoutContext.Provider>\n}\n\nexport function useAssistantLayout(): AssistantLayoutContextValue {\n const ctx = React.useContext(AssistantLayoutContext)\n if (!ctx) throw new Error(\"useAssistantLayout must be used within an AssistantLayoutProvider\")\n return ctx\n}\n\n// ---------------------------------------------------------------------------\n// Dock controls (segmented icon control for a top bar)\n// ---------------------------------------------------------------------------\n\nconst DOCK_OPTIONS: { value: AssistantDock; label: string; Icon: typeof PanelLeft }[] = [\n { value: \"left\", label: \"Dock assistant left\", Icon: PanelLeft },\n { value: \"bottom\", label: \"Dock assistant bottom\", Icon: PanelBottom },\n { value: \"right\", label: \"Dock assistant right\", Icon: PanelRight },\n]\n\nexport interface AssistantDockControlsProps {\n /** Label shown before the icons. Pass `null` to hide it. */\n label?: React.ReactNode\n className?: string\n}\n\n/**\n * Segmented control of dock icons. Clicking an inactive icon docks + shows the\n * assistant there; clicking the active icon again hides it.\n */\nexport function AssistantDockControls({ label = \"AI Assistant\", className }: AssistantDockControlsProps) {\n const { dock, setDock, visible, setVisible } = useAssistantLayout()\n\n return (\n <div className={cn(\"flex items-center gap-2\", className)}>\n {label != null && <span className=\"text-sm font-medium\">{label}</span>}\n <div className=\"inline-flex overflow-hidden rounded-lg border border-border\">\n {DOCK_OPTIONS.map(({ value, label: optionLabel, Icon }) => {\n const active = visible && dock === value\n return (\n <Button\n key={value}\n variant={active ? \"secondary\" : \"ghost\"}\n size=\"icon-sm\"\n // bg-clip-border so the filled (active/hover) state reaches the\n // cell edge instead of leaving a 1px gap from the button's\n // transparent border + default bg-clip-padding.\n className=\"rounded-none bg-clip-border\"\n aria-label={active ? \"Hide AI Assistant\" : optionLabel}\n aria-pressed={active}\n title={active ? \"Hide AI Assistant\" : optionLabel}\n onClick={() => {\n if (active) setVisible(false)\n else {\n setDock(value)\n setVisible(true)\n }\n }}\n >\n <Icon className=\"size-4\" />\n </Button>\n )\n })}\n </div>\n </div>\n )\n}\n\n// ---------------------------------------------------------------------------\n// Layout body\n// ---------------------------------------------------------------------------\n\n// Each panel is padded so the resize handle sits in a comfortable gutter between\n// the cards rather than a hairline seam (SW-2096). The padding lives inside the\n// panel box, so react-resizable-panels' flex sizing is unaffected.\nconst PANEL_PAD = \"flex min-h-0 min-w-0 p-2\"\n// The visible card surface rendered inside each panel.\nconst CARD_CLASS =\n \"flex h-full min-h-0 min-w-0 flex-1 flex-col overflow-hidden rounded-lg border border-border bg-card\"\n\nconst ASSISTANT_PANEL_ID = \"assistant\"\n\nexport interface AssistantLayoutProps {\n /** The AI Assistant panel content (e.g. a `<Chat />`). */\n assistant: React.ReactNode\n /** The main content; fills the remaining space (and the whole body when the assistant is hidden). */\n children: React.ReactNode\n /**\n * Title for the assistant panel's header cap (SW-2592). When set, the panel\n * renders a tinted (`bg-accent`) header band above `assistant` — the thing\n * that makes the assistant panel read as distinct from the content panel\n * (both are otherwise the same `bg-card` card). Omit to keep the panel a plain\n * card whose chrome you supply inside `assistant` (backward compatible).\n */\n assistantTitle?: React.ReactNode\n /** Optional element before the title in the header cap (e.g. an icon). */\n assistantIcon?: React.ReactNode\n /** Extra elements in the header cap, before the close button. */\n assistantHeaderActions?: React.ReactNode\n /** Render a close button in the header cap that hides the panel. Defaults to `true` when `assistantTitle` is set. */\n showAssistantClose?: boolean\n /** Min assistant size as a percentage of the layout. */\n minSize?: number\n /** Max assistant size as a percentage of the layout. */\n maxSize?: number\n className?: string\n assistantClassName?: string\n contentClassName?: string\n}\n\n/**\n * Docks the assistant left / right / bottom of the main content and resizes it\n * with the design-system `Resizable` (react-resizable-panels). Must be rendered\n * inside an `AssistantLayoutProvider`; pair with `AssistantDockControls`.\n *\n * The group is keyed by `dock`, so changing dock remounts the panels. The\n * assistant panel is therefore re-created on redock (its transient state is not\n * preserved across a dock change) — a deliberate trade-off for using the shared\n * resizable primitive rather than a bespoke splitter.\n */\nexport function AssistantLayout({\n assistant,\n children,\n assistantTitle,\n assistantIcon,\n assistantHeaderActions,\n showAssistantClose,\n minSize = 20,\n maxSize = 70,\n className,\n assistantClassName,\n contentClassName,\n}: AssistantLayoutProps) {\n const { dock, size, setSize, visible, setVisible } = useAssistantLayout()\n const { orientation, assistantFirst } = dockPanels(dock)\n\n // Accent header cap — the assistant panel's brand band. Only rendered when a\n // title is provided; content panel never gets one, so the two panels read as\n // distinct even though both are `bg-card` (SW-2592).\n const showClose = showAssistantClose ?? assistantTitle != null\n const assistantHeader = assistantTitle != null && (\n <div\n data-slot=\"assistant-layout-assistant-header\"\n className=\"flex shrink-0 items-center gap-2 border-b border-primary/15 bg-accent px-3 py-2\"\n >\n {assistantIcon != null && <span className=\"flex shrink-0 items-center justify-center\">{assistantIcon}</span>}\n <span className=\"min-w-0 flex-1 truncate text-sm font-semibold text-foreground\">{assistantTitle}</span>\n {assistantHeaderActions}\n {showClose && (\n <Button\n variant=\"ghost\"\n size=\"icon-sm\"\n className=\"text-muted-foreground\"\n aria-label=\"Hide assistant\"\n onClick={() => setVisible(false)}\n >\n <X />\n </Button>\n )}\n </div>\n )\n\n // Hidden: no resizable group, content fills the whole body.\n if (!visible) {\n return (\n <div\n data-slot=\"assistant-layout\"\n className={cn(\"flex min-h-0 flex-1 overflow-hidden\", className)}\n >\n {/* flex-1 so the lone content panel fills the width (the ResizablePanel\n self-sizes when visible; this plain div needs to be told to grow).\n Padded to match the inset the visible panels carry. */}\n <div className={cn(PANEL_PAD, \"flex-1\")}>\n <div data-slot=\"assistant-layout-content\" className={cn(CARD_CLASS, contentClassName)}>\n {children}\n </div>\n </div>\n </div>\n )\n }\n\n const assistantPanel = (\n <ResizablePanel\n id={ASSISTANT_PANEL_ID}\n defaultSize={`${size}%`}\n minSize={`${minSize}%`}\n maxSize={`${maxSize}%`}\n className={PANEL_PAD}\n >\n <div data-slot=\"assistant-layout-assistant\" className={cn(CARD_CLASS, assistantClassName)}>\n {assistantHeader}\n {assistant}\n </div>\n </ResizablePanel>\n )\n\n const contentPanel = (\n <ResizablePanel id=\"content\" className={PANEL_PAD}>\n <div data-slot=\"assistant-layout-content\" className={cn(CARD_CLASS, contentClassName)}>\n {children}\n </div>\n </ResizablePanel>\n )\n\n return (\n <ResizablePanelGroup\n key={dock}\n orientation={orientation}\n data-slot=\"assistant-layout\"\n className={cn(\"min-h-0 flex-1 overflow-hidden\", className)}\n onLayoutChanged={(layout) => {\n const pct = layout[ASSISTANT_PANEL_ID]\n if (typeof pct === \"number\") setSize(pct)\n }}\n >\n {assistantFirst ? (\n <>\n {assistantPanel}\n <ResizableHandle withHandle />\n {contentPanel}\n </>\n ) : (\n <>\n {contentPanel}\n <ResizableHandle withHandle />\n {assistantPanel}\n </>\n )}\n </ResizablePanelGroup>\n )\n}\n"],"names":["AssistantLayoutContext","React","readDock","key","fallback","v","readSize","AssistantLayoutProvider","children","storageKey","defaultDock","defaultSize","defaultVisible","persist","dock","setDockState","size","setSizeState","visible","setVisible","setDock","next","setSize","value","jsx","useAssistantLayout","ctx","DOCK_OPTIONS","PanelLeft","PanelBottom","PanelRight","AssistantDockControls","label","className","cn","optionLabel","Icon","active","Button","PANEL_PAD","CARD_CLASS","ASSISTANT_PANEL_ID","AssistantLayout","assistant","assistantTitle","assistantIcon","assistantHeaderActions","showAssistantClose","minSize","maxSize","assistantClassName","contentClassName","orientation","assistantFirst","dockPanels","showClose","assistantHeader","jsxs","X","assistantPanel","ResizablePanel","contentPanel","ResizablePanelGroup","layout","pct","Fragment","ResizableHandle"],"mappings":"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"}
@@ -41,6 +41,20 @@ export interface AssistantLayoutProps {
41
41
  assistant: React.ReactNode;
42
42
  /** The main content; fills the remaining space (and the whole body when the assistant is hidden). */
43
43
  children: React.ReactNode;
44
+ /**
45
+ * Title for the assistant panel's header cap (SW-2592). When set, the panel
46
+ * renders a tinted (`bg-accent`) header band above `assistant` — the thing
47
+ * that makes the assistant panel read as distinct from the content panel
48
+ * (both are otherwise the same `bg-card` card). Omit to keep the panel a plain
49
+ * card whose chrome you supply inside `assistant` (backward compatible).
50
+ */
51
+ assistantTitle?: React.ReactNode;
52
+ /** Optional element before the title in the header cap (e.g. an icon). */
53
+ assistantIcon?: React.ReactNode;
54
+ /** Extra elements in the header cap, before the close button. */
55
+ assistantHeaderActions?: React.ReactNode;
56
+ /** Render a close button in the header cap that hides the panel. Defaults to `true` when `assistantTitle` is set. */
57
+ showAssistantClose?: boolean;
44
58
  /** Min assistant size as a percentage of the layout. */
45
59
  minSize?: number;
46
60
  /** Max assistant size as a percentage of the layout. */
@@ -59,5 +73,5 @@ export interface AssistantLayoutProps {
59
73
  * preserved across a dock change) — a deliberate trade-off for using the shared
60
74
  * resizable primitive rather than a bespoke splitter.
61
75
  */
62
- export declare function AssistantLayout({ assistant, children, minSize, maxSize, className, assistantClassName, contentClassName, }: AssistantLayoutProps): import("react/jsx-runtime").JSX.Element;
76
+ export declare function AssistantLayout({ assistant, children, assistantTitle, assistantIcon, assistantHeaderActions, showAssistantClose, minSize, maxSize, className, assistantClassName, contentClassName, }: AssistantLayoutProps): import("react/jsx-runtime").JSX.Element;
63
77
  export {};
@@ -1,142 +1,171 @@
1
- import { jsxs as N, jsx as n, Fragment as z } from "react/jsx-runtime";
2
- import { PanelLeft as D, PanelBottom as C, PanelRight as L } from "lucide-react";
1
+ import { jsxs as b, jsx as e, Fragment as y } from "react/jsx-runtime";
2
+ import { PanelLeft as E, PanelBottom as F, PanelRight as O, X as V } from "lucide-react";
3
3
  import * as l from "react";
4
- import { dockPanels as $ } from "./dockLayout.js";
5
- import { Button as R } from "../../../ui/button.js";
6
- import { ResizablePanel as P, ResizablePanelGroup as H, ResizableHandle as g } from "../../../ui/resizable.js";
7
- import { cn as d } from "../../../lib/utils.js";
8
- const y = l.createContext(null);
9
- function _(s, t) {
10
- if (typeof window > "u") return t;
11
- const e = window.localStorage.getItem(`${s}.dock`);
12
- return e === "right" || e === "bottom" || e === "left" ? e : t;
4
+ import { dockPanels as B } from "./dockLayout.js";
5
+ import { Button as I } from "../../../ui/button.js";
6
+ import { ResizablePanel as z, ResizablePanelGroup as M, ResizableHandle as P } from "../../../ui/resizable.js";
7
+ import { cn as u } from "../../../lib/utils.js";
8
+ const D = l.createContext(null);
9
+ function G(n, s) {
10
+ if (typeof window > "u") return s;
11
+ const t = window.localStorage.getItem(`${n}.dock`);
12
+ return t === "right" || t === "bottom" || t === "left" ? t : s;
13
13
  }
14
- function E(s, t) {
15
- if (typeof window > "u") return t;
16
- const e = Number(window.localStorage.getItem(`${s}.size`));
17
- return !Number.isFinite(e) || e <= 0 || e >= 100 ? t : e;
14
+ function T(n, s) {
15
+ if (typeof window > "u") return s;
16
+ const t = Number(window.localStorage.getItem(`${n}.size`));
17
+ return !Number.isFinite(t) || t <= 0 || t >= 100 ? s : t;
18
18
  }
19
- function G({
20
- children: s,
21
- storageKey: t = "ts-ui.assistant",
22
- defaultDock: e = "left",
23
- defaultSize: u = 32,
24
- defaultVisible: m = !0,
25
- persist: o = !0
19
+ function Z({
20
+ children: n,
21
+ storageKey: s = "ts-ui.assistant",
22
+ defaultDock: t = "left",
23
+ defaultSize: r = 32,
24
+ defaultVisible: f = !0,
25
+ persist: i = !0
26
26
  }) {
27
- const [i, r] = l.useState(
28
- () => o ? _(t, e) : e
29
- ), [f, a] = l.useState(
30
- () => o ? E(t, u) : u
31
- ), [b, S] = l.useState(m), w = l.useCallback(
32
- (c) => {
33
- r(c), o && typeof window < "u" && window.localStorage.setItem(`${t}.dock`, c);
27
+ const [a, m] = l.useState(
28
+ () => i ? G(s, t) : t
29
+ ), [c, o] = l.useState(
30
+ () => i ? T(s, r) : r
31
+ ), [h, w] = l.useState(f), v = l.useCallback(
32
+ (d) => {
33
+ m(d), i && typeof window < "u" && window.localStorage.setItem(`${s}.dock`, d);
34
34
  },
35
- [t, o]
36
- ), h = l.useCallback(
37
- (c) => {
38
- a(c), o && typeof window < "u" && window.localStorage.setItem(`${t}.size`, String(Math.round(c)));
35
+ [s, i]
36
+ ), x = l.useCallback(
37
+ (d) => {
38
+ o(d), i && typeof window < "u" && window.localStorage.setItem(`${s}.size`, String(Math.round(d)));
39
39
  },
40
- [t, o]
41
- ), v = l.useMemo(
42
- () => ({ dock: i, setDock: w, size: f, setSize: h, visible: b, setVisible: S }),
43
- [i, w, f, h, b]
40
+ [s, i]
41
+ ), S = l.useMemo(
42
+ () => ({ dock: a, setDock: v, size: c, setSize: x, visible: h, setVisible: w }),
43
+ [a, v, c, x, h]
44
44
  );
45
- return /* @__PURE__ */ n(y.Provider, { value: v, children: s });
45
+ return /* @__PURE__ */ e(D.Provider, { value: S, children: n });
46
46
  }
47
- function I() {
48
- const s = l.useContext(y);
49
- if (!s) throw new Error("useAssistantLayout must be used within an AssistantLayoutProvider");
50
- return s;
47
+ function L() {
48
+ const n = l.useContext(D);
49
+ if (!n) throw new Error("useAssistantLayout must be used within an AssistantLayoutProvider");
50
+ return n;
51
51
  }
52
- const F = [
53
- { value: "left", label: "Dock assistant left", Icon: D },
54
- { value: "bottom", label: "Dock assistant bottom", Icon: C },
55
- { value: "right", label: "Dock assistant right", Icon: L }
52
+ const X = [
53
+ { value: "left", label: "Dock assistant left", Icon: E },
54
+ { value: "bottom", label: "Dock assistant bottom", Icon: F },
55
+ { value: "right", label: "Dock assistant right", Icon: O }
56
56
  ];
57
- function q({ label: s = "AI Assistant", className: t }) {
58
- const { dock: e, setDock: u, visible: m, setVisible: o } = I();
59
- return /* @__PURE__ */ N("div", { className: d("flex items-center gap-2", t), children: [
60
- s != null && /* @__PURE__ */ n("span", { className: "text-sm font-medium", children: s }),
61
- /* @__PURE__ */ n("div", { className: "inline-flex overflow-hidden rounded-lg border border-border", children: F.map(({ value: i, label: r, Icon: f }) => {
62
- const a = m && e === i;
63
- return /* @__PURE__ */ n(
64
- R,
57
+ function K({ label: n = "AI Assistant", className: s }) {
58
+ const { dock: t, setDock: r, visible: f, setVisible: i } = L();
59
+ return /* @__PURE__ */ b("div", { className: u("flex items-center gap-2", s), children: [
60
+ n != null && /* @__PURE__ */ e("span", { className: "text-sm font-medium", children: n }),
61
+ /* @__PURE__ */ e("div", { className: "inline-flex overflow-hidden rounded-lg border border-border", children: X.map(({ value: a, label: m, Icon: c }) => {
62
+ const o = f && t === a;
63
+ return /* @__PURE__ */ e(
64
+ I,
65
65
  {
66
- variant: a ? "secondary" : "ghost",
66
+ variant: o ? "secondary" : "ghost",
67
67
  size: "icon-sm",
68
68
  className: "rounded-none bg-clip-border",
69
- "aria-label": a ? "Hide AI Assistant" : r,
70
- "aria-pressed": a,
71
- title: a ? "Hide AI Assistant" : r,
69
+ "aria-label": o ? "Hide AI Assistant" : m,
70
+ "aria-pressed": o,
71
+ title: o ? "Hide AI Assistant" : m,
72
72
  onClick: () => {
73
- a ? o(!1) : (u(i), o(!0));
73
+ o ? i(!1) : (r(a), i(!0));
74
74
  },
75
- children: /* @__PURE__ */ n(f, { className: "size-4" })
75
+ children: /* @__PURE__ */ e(c, { className: "size-4" })
76
76
  },
77
- i
77
+ a
78
78
  );
79
79
  }) })
80
80
  ] });
81
81
  }
82
- const A = "flex min-h-0 min-w-0 p-2", x = "flex h-full min-h-0 min-w-0 flex-1 flex-col overflow-hidden rounded-lg border border-border bg-card", k = "assistant";
83
- function J({
84
- assistant: s,
85
- children: t,
86
- minSize: e = 20,
87
- maxSize: u = 70,
88
- className: m,
82
+ const p = "flex min-h-0 min-w-0 p-2", N = "flex h-full min-h-0 min-w-0 flex-1 flex-col overflow-hidden rounded-lg border border-border bg-card", C = "assistant";
83
+ function tt({
84
+ assistant: n,
85
+ children: s,
86
+ assistantTitle: t,
87
+ assistantIcon: r,
88
+ assistantHeaderActions: f,
89
+ showAssistantClose: i,
90
+ minSize: a = 20,
91
+ maxSize: m = 70,
92
+ className: c,
89
93
  assistantClassName: o,
90
- contentClassName: i
94
+ contentClassName: h
91
95
  }) {
92
- const { dock: r, size: f, setSize: a, visible: b } = I(), { orientation: S, assistantFirst: w } = $(r);
93
- if (!b)
94
- return /* @__PURE__ */ n(
96
+ const { dock: w, size: v, setSize: x, visible: S, setVisible: d } = L(), { orientation: H, assistantFirst: $ } = B(w), R = i ?? t != null, _ = t != null && /* @__PURE__ */ b(
97
+ "div",
98
+ {
99
+ "data-slot": "assistant-layout-assistant-header",
100
+ className: "flex shrink-0 items-center gap-2 border-b border-primary/15 bg-accent px-3 py-2",
101
+ children: [
102
+ r != null && /* @__PURE__ */ e("span", { className: "flex shrink-0 items-center justify-center", children: r }),
103
+ /* @__PURE__ */ e("span", { className: "min-w-0 flex-1 truncate text-sm font-semibold text-foreground", children: t }),
104
+ f,
105
+ R && /* @__PURE__ */ e(
106
+ I,
107
+ {
108
+ variant: "ghost",
109
+ size: "icon-sm",
110
+ className: "text-muted-foreground",
111
+ "aria-label": "Hide assistant",
112
+ onClick: () => d(!1),
113
+ children: /* @__PURE__ */ e(V, {})
114
+ }
115
+ )
116
+ ]
117
+ }
118
+ );
119
+ if (!S)
120
+ return /* @__PURE__ */ e(
95
121
  "div",
96
122
  {
97
123
  "data-slot": "assistant-layout",
98
- className: d("flex min-h-0 flex-1 overflow-hidden", m),
99
- children: /* @__PURE__ */ n("div", { className: d(A, "flex-1"), children: /* @__PURE__ */ n("div", { "data-slot": "assistant-layout-content", className: d(x, i), children: t }) })
124
+ className: u("flex min-h-0 flex-1 overflow-hidden", c),
125
+ children: /* @__PURE__ */ e("div", { className: u(p, "flex-1"), children: /* @__PURE__ */ e("div", { "data-slot": "assistant-layout-content", className: u(N, h), children: s }) })
100
126
  }
101
127
  );
102
- const h = /* @__PURE__ */ n(
103
- P,
128
+ const A = /* @__PURE__ */ e(
129
+ z,
104
130
  {
105
- id: k,
106
- defaultSize: `${f}%`,
107
- minSize: `${e}%`,
108
- maxSize: `${u}%`,
109
- className: A,
110
- children: /* @__PURE__ */ n("div", { "data-slot": "assistant-layout-assistant", className: d(x, o), children: s })
131
+ id: C,
132
+ defaultSize: `${v}%`,
133
+ minSize: `${a}%`,
134
+ maxSize: `${m}%`,
135
+ className: p,
136
+ children: /* @__PURE__ */ b("div", { "data-slot": "assistant-layout-assistant", className: u(N, o), children: [
137
+ _,
138
+ n
139
+ ] })
111
140
  }
112
- ), v = /* @__PURE__ */ n(P, { id: "content", className: A, children: /* @__PURE__ */ n("div", { "data-slot": "assistant-layout-content", className: d(x, i), children: t }) });
113
- return /* @__PURE__ */ n(
114
- H,
141
+ ), g = /* @__PURE__ */ e(z, { id: "content", className: p, children: /* @__PURE__ */ e("div", { "data-slot": "assistant-layout-content", className: u(N, h), children: s }) });
142
+ return /* @__PURE__ */ e(
143
+ M,
115
144
  {
116
- orientation: S,
145
+ orientation: H,
117
146
  "data-slot": "assistant-layout",
118
- className: d("min-h-0 flex-1 overflow-hidden", m),
119
- onLayoutChanged: (c) => {
120
- const p = c[k];
121
- typeof p == "number" && a(p);
147
+ className: u("min-h-0 flex-1 overflow-hidden", c),
148
+ onLayoutChanged: (j) => {
149
+ const k = j[C];
150
+ typeof k == "number" && x(k);
122
151
  },
123
- children: w ? /* @__PURE__ */ N(z, { children: [
124
- h,
125
- /* @__PURE__ */ n(g, { withHandle: !0 }),
126
- v
127
- ] }) : /* @__PURE__ */ N(z, { children: [
128
- v,
129
- /* @__PURE__ */ n(g, { withHandle: !0 }),
130
- h
152
+ children: $ ? /* @__PURE__ */ b(y, { children: [
153
+ A,
154
+ /* @__PURE__ */ e(P, { withHandle: !0 }),
155
+ g
156
+ ] }) : /* @__PURE__ */ b(y, { children: [
157
+ g,
158
+ /* @__PURE__ */ e(P, { withHandle: !0 }),
159
+ A
131
160
  ] })
132
161
  },
133
- r
162
+ w
134
163
  );
135
164
  }
136
165
  export {
137
- q as AssistantDockControls,
138
- J as AssistantLayout,
139
- G as AssistantLayoutProvider,
140
- I as useAssistantLayout
166
+ K as AssistantDockControls,
167
+ tt as AssistantLayout,
168
+ Z as AssistantLayoutProvider,
169
+ L as useAssistantLayout
141
170
  };
142
171
  //# sourceMappingURL=AssistantLayout.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"AssistantLayout.js","sources":["../../../../src/components/composed/AssistantLayout/AssistantLayout.tsx"],"sourcesContent":["\"use client\"\n\nimport { PanelBottom, PanelLeft, PanelRight } from \"lucide-react\"\nimport * as React from \"react\"\n\nimport { dockPanels, type AssistantDock } from \"./dockLayout\"\n\nimport { Button } from \"@/components/ui/button\"\nimport {\n ResizableHandle,\n ResizablePanel,\n ResizablePanelGroup,\n} from \"@/components/ui/resizable\"\nimport { cn } from \"@/lib/utils\"\n\n// ---------------------------------------------------------------------------\n// Context + provider\n// ---------------------------------------------------------------------------\n\ninterface AssistantLayoutContextValue {\n /** Where the assistant docks. Persisted. */\n dock: AssistantDock\n setDock: (dock: AssistantDock) => void\n /** Assistant size as a percentage of the layout along the dock axis. Persisted. */\n size: number\n setSize: (size: number) => void\n /** Whether the assistant is shown. In-memory by default (resets to visible on reload). */\n visible: boolean\n setVisible: (visible: boolean) => void\n}\n\nconst AssistantLayoutContext = React.createContext<AssistantLayoutContextValue | null>(null)\n\nexport interface AssistantLayoutProviderProps {\n children: React.ReactNode\n /** localStorage key prefix for the persisted dock + size. */\n storageKey?: string\n /** Default dock when nothing is persisted. */\n defaultDock?: AssistantDock\n /** Default assistant size as a percentage (1–99) of the layout. */\n defaultSize?: number\n /** Whether the assistant starts visible. */\n defaultVisible?: boolean\n /** Persist dock + size to localStorage. Defaults to `true`. */\n persist?: boolean\n}\n\nfunction readDock(key: string, fallback: AssistantDock): AssistantDock {\n if (typeof window === \"undefined\") return fallback\n const v = window.localStorage.getItem(`${key}.dock`)\n return v === \"right\" || v === \"bottom\" || v === \"left\" ? v : fallback\n}\n\nfunction readSize(key: string, fallback: number): number {\n if (typeof window === \"undefined\") return fallback\n const v = Number(window.localStorage.getItem(`${key}.size`))\n // Persisted as a percentage; ignore anything outside the open (0, 100) range.\n if (!Number.isFinite(v) || v <= 0 || v >= 100) return fallback\n return v\n}\n\nexport function AssistantLayoutProvider({\n children,\n storageKey = \"ts-ui.assistant\",\n defaultDock = \"left\",\n defaultSize = 32,\n defaultVisible = true,\n persist = true,\n}: AssistantLayoutProviderProps) {\n const [dock, setDockState] = React.useState<AssistantDock>(() =>\n persist ? readDock(storageKey, defaultDock) : defaultDock\n )\n const [size, setSizeState] = React.useState<number>(() =>\n persist ? readSize(storageKey, defaultSize) : defaultSize\n )\n const [visible, setVisible] = React.useState(defaultVisible)\n\n const setDock = React.useCallback(\n (next: AssistantDock) => {\n setDockState(next)\n if (persist && typeof window !== \"undefined\")\n window.localStorage.setItem(`${storageKey}.dock`, next)\n },\n [storageKey, persist]\n )\n\n const setSize = React.useCallback(\n (next: number) => {\n setSizeState(next)\n if (persist && typeof window !== \"undefined\")\n window.localStorage.setItem(`${storageKey}.size`, String(Math.round(next)))\n },\n [storageKey, persist]\n )\n\n const value = React.useMemo(\n () => ({ dock, setDock, size, setSize, visible, setVisible }),\n [dock, setDock, size, setSize, visible]\n )\n\n return <AssistantLayoutContext.Provider value={value}>{children}</AssistantLayoutContext.Provider>\n}\n\nexport function useAssistantLayout(): AssistantLayoutContextValue {\n const ctx = React.useContext(AssistantLayoutContext)\n if (!ctx) throw new Error(\"useAssistantLayout must be used within an AssistantLayoutProvider\")\n return ctx\n}\n\n// ---------------------------------------------------------------------------\n// Dock controls (segmented icon control for a top bar)\n// ---------------------------------------------------------------------------\n\nconst DOCK_OPTIONS: { value: AssistantDock; label: string; Icon: typeof PanelLeft }[] = [\n { value: \"left\", label: \"Dock assistant left\", Icon: PanelLeft },\n { value: \"bottom\", label: \"Dock assistant bottom\", Icon: PanelBottom },\n { value: \"right\", label: \"Dock assistant right\", Icon: PanelRight },\n]\n\nexport interface AssistantDockControlsProps {\n /** Label shown before the icons. Pass `null` to hide it. */\n label?: React.ReactNode\n className?: string\n}\n\n/**\n * Segmented control of dock icons. Clicking an inactive icon docks + shows the\n * assistant there; clicking the active icon again hides it.\n */\nexport function AssistantDockControls({ label = \"AI Assistant\", className }: AssistantDockControlsProps) {\n const { dock, setDock, visible, setVisible } = useAssistantLayout()\n\n return (\n <div className={cn(\"flex items-center gap-2\", className)}>\n {label != null && <span className=\"text-sm font-medium\">{label}</span>}\n <div className=\"inline-flex overflow-hidden rounded-lg border border-border\">\n {DOCK_OPTIONS.map(({ value, label: optionLabel, Icon }) => {\n const active = visible && dock === value\n return (\n <Button\n key={value}\n variant={active ? \"secondary\" : \"ghost\"}\n size=\"icon-sm\"\n // bg-clip-border so the filled (active/hover) state reaches the\n // cell edge instead of leaving a 1px gap from the button's\n // transparent border + default bg-clip-padding.\n className=\"rounded-none bg-clip-border\"\n aria-label={active ? \"Hide AI Assistant\" : optionLabel}\n aria-pressed={active}\n title={active ? \"Hide AI Assistant\" : optionLabel}\n onClick={() => {\n if (active) setVisible(false)\n else {\n setDock(value)\n setVisible(true)\n }\n }}\n >\n <Icon className=\"size-4\" />\n </Button>\n )\n })}\n </div>\n </div>\n )\n}\n\n// ---------------------------------------------------------------------------\n// Layout body\n// ---------------------------------------------------------------------------\n\n// Each panel is padded so the resize handle sits in a comfortable gutter between\n// the cards rather than a hairline seam (SW-2096). The padding lives inside the\n// panel box, so react-resizable-panels' flex sizing is unaffected.\nconst PANEL_PAD = \"flex min-h-0 min-w-0 p-2\"\n// The visible card surface rendered inside each panel.\nconst CARD_CLASS =\n \"flex h-full min-h-0 min-w-0 flex-1 flex-col overflow-hidden rounded-lg border border-border bg-card\"\n\nconst ASSISTANT_PANEL_ID = \"assistant\"\n\nexport interface AssistantLayoutProps {\n /** The AI Assistant panel content (e.g. a `<Chat />`). */\n assistant: React.ReactNode\n /** The main content; fills the remaining space (and the whole body when the assistant is hidden). */\n children: React.ReactNode\n /** Min assistant size as a percentage of the layout. */\n minSize?: number\n /** Max assistant size as a percentage of the layout. */\n maxSize?: number\n className?: string\n assistantClassName?: string\n contentClassName?: string\n}\n\n/**\n * Docks the assistant left / right / bottom of the main content and resizes it\n * with the design-system `Resizable` (react-resizable-panels). Must be rendered\n * inside an `AssistantLayoutProvider`; pair with `AssistantDockControls`.\n *\n * The group is keyed by `dock`, so changing dock remounts the panels. The\n * assistant panel is therefore re-created on redock (its transient state is not\n * preserved across a dock change) — a deliberate trade-off for using the shared\n * resizable primitive rather than a bespoke splitter.\n */\nexport function AssistantLayout({\n assistant,\n children,\n minSize = 20,\n maxSize = 70,\n className,\n assistantClassName,\n contentClassName,\n}: AssistantLayoutProps) {\n const { dock, size, setSize, visible } = useAssistantLayout()\n const { orientation, assistantFirst } = dockPanels(dock)\n\n // Hidden: no resizable group, content fills the whole body.\n if (!visible) {\n return (\n <div\n data-slot=\"assistant-layout\"\n className={cn(\"flex min-h-0 flex-1 overflow-hidden\", className)}\n >\n {/* flex-1 so the lone content panel fills the width (the ResizablePanel\n self-sizes when visible; this plain div needs to be told to grow).\n Padded to match the inset the visible panels carry. */}\n <div className={cn(PANEL_PAD, \"flex-1\")}>\n <div data-slot=\"assistant-layout-content\" className={cn(CARD_CLASS, contentClassName)}>\n {children}\n </div>\n </div>\n </div>\n )\n }\n\n const assistantPanel = (\n <ResizablePanel\n id={ASSISTANT_PANEL_ID}\n defaultSize={`${size}%`}\n minSize={`${minSize}%`}\n maxSize={`${maxSize}%`}\n className={PANEL_PAD}\n >\n <div data-slot=\"assistant-layout-assistant\" className={cn(CARD_CLASS, assistantClassName)}>\n {assistant}\n </div>\n </ResizablePanel>\n )\n\n const contentPanel = (\n <ResizablePanel id=\"content\" className={PANEL_PAD}>\n <div data-slot=\"assistant-layout-content\" className={cn(CARD_CLASS, contentClassName)}>\n {children}\n </div>\n </ResizablePanel>\n )\n\n return (\n <ResizablePanelGroup\n key={dock}\n orientation={orientation}\n data-slot=\"assistant-layout\"\n className={cn(\"min-h-0 flex-1 overflow-hidden\", className)}\n onLayoutChanged={(layout) => {\n const pct = layout[ASSISTANT_PANEL_ID]\n if (typeof pct === \"number\") setSize(pct)\n }}\n >\n {assistantFirst ? (\n <>\n {assistantPanel}\n <ResizableHandle withHandle />\n {contentPanel}\n </>\n ) : (\n <>\n {contentPanel}\n <ResizableHandle withHandle />\n {assistantPanel}\n </>\n )}\n </ResizablePanelGroup>\n )\n}\n"],"names":["AssistantLayoutContext","React","readDock","key","fallback","v","readSize","AssistantLayoutProvider","children","storageKey","defaultDock","defaultSize","defaultVisible","persist","dock","setDockState","size","setSizeState","visible","setVisible","setDock","next","setSize","value","jsx","useAssistantLayout","ctx","DOCK_OPTIONS","PanelLeft","PanelBottom","PanelRight","AssistantDockControls","label","className","cn","optionLabel","Icon","active","Button","PANEL_PAD","CARD_CLASS","ASSISTANT_PANEL_ID","AssistantLayout","assistant","minSize","maxSize","assistantClassName","contentClassName","orientation","assistantFirst","dockPanels","assistantPanel","ResizablePanel","contentPanel","ResizablePanelGroup","layout","pct","jsxs","Fragment","ResizableHandle"],"mappings":";;;;;;;AA+BA,MAAMA,IAAyBC,EAAM,cAAkD,IAAI;AAgB3F,SAASC,EAASC,GAAaC,GAAwC;AACrE,MAAI,OAAO,SAAW,IAAa,QAAOA;AAC1C,QAAMC,IAAI,OAAO,aAAa,QAAQ,GAAGF,CAAG,OAAO;AACnD,SAAOE,MAAM,WAAWA,MAAM,YAAYA,MAAM,SAASA,IAAID;AAC/D;AAEA,SAASE,EAASH,GAAaC,GAA0B;AACvD,MAAI,OAAO,SAAW,IAAa,QAAOA;AAC1C,QAAMC,IAAI,OAAO,OAAO,aAAa,QAAQ,GAAGF,CAAG,OAAO,CAAC;AAE3D,SAAI,CAAC,OAAO,SAASE,CAAC,KAAKA,KAAK,KAAKA,KAAK,MAAYD,IAC/CC;AACT;AAEO,SAASE,EAAwB;AAAA,EACtC,UAAAC;AAAA,EACA,YAAAC,IAAa;AAAA,EACb,aAAAC,IAAc;AAAA,EACd,aAAAC,IAAc;AAAA,EACd,gBAAAC,IAAiB;AAAA,EACjB,SAAAC,IAAU;AACZ,GAAiC;AAC/B,QAAM,CAACC,GAAMC,CAAY,IAAId,EAAM;AAAA,IAAwB,MACzDY,IAAUX,EAASO,GAAYC,CAAW,IAAIA;AAAA,EAAA,GAE1C,CAACM,GAAMC,CAAY,IAAIhB,EAAM;AAAA,IAAiB,MAClDY,IAAUP,EAASG,GAAYE,CAAW,IAAIA;AAAA,EAAA,GAE1C,CAACO,GAASC,CAAU,IAAIlB,EAAM,SAASW,CAAc,GAErDQ,IAAUnB,EAAM;AAAA,IACpB,CAACoB,MAAwB;AACvB,MAAAN,EAAaM,CAAI,GACbR,KAAW,OAAO,SAAW,OAC/B,OAAO,aAAa,QAAQ,GAAGJ,CAAU,SAASY,CAAI;AAAA,IAC1D;AAAA,IACA,CAACZ,GAAYI,CAAO;AAAA,EAAA,GAGhBS,IAAUrB,EAAM;AAAA,IACpB,CAACoB,MAAiB;AAChB,MAAAJ,EAAaI,CAAI,GACbR,KAAW,OAAO,SAAW,OAC/B,OAAO,aAAa,QAAQ,GAAGJ,CAAU,SAAS,OAAO,KAAK,MAAMY,CAAI,CAAC,CAAC;AAAA,IAC9E;AAAA,IACA,CAACZ,GAAYI,CAAO;AAAA,EAAA,GAGhBU,IAAQtB,EAAM;AAAA,IAClB,OAAO,EAAE,MAAAa,GAAM,SAAAM,GAAS,MAAAJ,GAAM,SAAAM,GAAS,SAAAJ,GAAS,YAAAC;IAChD,CAACL,GAAMM,GAASJ,GAAMM,GAASJ,CAAO;AAAA,EAAA;AAGxC,SAAO,gBAAAM,EAACxB,EAAuB,UAAvB,EAAgC,OAAAuB,GAAe,UAAAf,EAAA,CAAS;AAClE;AAEO,SAASiB,IAAkD;AAChE,QAAMC,IAAMzB,EAAM,WAAWD,CAAsB;AACnD,MAAI,CAAC0B,EAAK,OAAM,IAAI,MAAM,mEAAmE;AAC7F,SAAOA;AACT;AAMA,MAAMC,IAAkF;AAAA,EACtF,EAAE,OAAO,QAAQ,OAAO,uBAAuB,MAAMC,EAAA;AAAA,EACrD,EAAE,OAAO,UAAU,OAAO,yBAAyB,MAAMC,EAAA;AAAA,EACzD,EAAE,OAAO,SAAS,OAAO,wBAAwB,MAAMC,EAAA;AACzD;AAYO,SAASC,EAAsB,EAAE,OAAAC,IAAQ,gBAAgB,WAAAC,KAAyC;AACvG,QAAM,EAAE,MAAAnB,GAAM,SAAAM,GAAS,SAAAF,GAAS,YAAAC,EAAA,IAAeM,EAAA;AAE/C,2BACG,OAAA,EAAI,WAAWS,EAAG,2BAA2BD,CAAS,GACpD,UAAA;AAAA,IAAAD,KAAS,QAAQ,gBAAAR,EAAC,QAAA,EAAK,WAAU,uBAAuB,UAAAQ,GAAM;AAAA,IAC/D,gBAAAR,EAAC,OAAA,EAAI,WAAU,+DACZ,UAAAG,EAAa,IAAI,CAAC,EAAE,OAAAJ,GAAO,OAAOY,GAAa,MAAAC,EAAA,MAAW;AACzD,YAAMC,IAASnB,KAAWJ,MAASS;AACnC,aACE,gBAAAC;AAAA,QAACc;AAAA,QAAA;AAAA,UAEC,SAASD,IAAS,cAAc;AAAA,UAChC,MAAK;AAAA,UAIL,WAAU;AAAA,UACV,cAAYA,IAAS,sBAAsBF;AAAA,UAC3C,gBAAcE;AAAA,UACd,OAAOA,IAAS,sBAAsBF;AAAA,UACtC,SAAS,MAAM;AACb,YAAIE,MAAmB,EAAK,KAE1BjB,EAAQG,CAAK,GACbJ,EAAW,EAAI;AAAA,UAEnB;AAAA,UAEA,UAAA,gBAAAK,EAACY,GAAA,EAAK,WAAU,SAAA,CAAS;AAAA,QAAA;AAAA,QAlBpBb;AAAA,MAAA;AAAA,IAqBX,CAAC,EAAA,CACH;AAAA,EAAA,GACF;AAEJ;AASA,MAAMgB,IAAY,4BAEZC,IACJ,uGAEIC,IAAqB;AA0BpB,SAASC,EAAgB;AAAA,EAC9B,WAAAC;AAAA,EACA,UAAAnC;AAAA,EACA,SAAAoC,IAAU;AAAA,EACV,SAAAC,IAAU;AAAA,EACV,WAAAZ;AAAA,EACA,oBAAAa;AAAA,EACA,kBAAAC;AACF,GAAyB;AACvB,QAAM,EAAE,MAAAjC,GAAM,MAAAE,GAAM,SAAAM,GAAS,SAAAJ,EAAA,IAAYO,EAAA,GACnC,EAAE,aAAAuB,GAAa,gBAAAC,MAAmBC,EAAWpC,CAAI;AAGvD,MAAI,CAACI;AACH,WACE,gBAAAM;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,aAAU;AAAA,QACV,WAAWU,EAAG,uCAAuCD,CAAS;AAAA,QAK9D,4BAAC,OAAA,EAAI,WAAWC,EAAGK,GAAW,QAAQ,GACpC,UAAA,gBAAAf,EAAC,OAAA,EAAI,aAAU,4BAA2B,WAAWU,EAAGM,GAAYO,CAAgB,GACjF,UAAAvC,GACH,EAAA,CACF;AAAA,MAAA;AAAA,IAAA;AAKN,QAAM2C,IACJ,gBAAA3B;AAAA,IAAC4B;AAAA,IAAA;AAAA,MACC,IAAIX;AAAA,MACJ,aAAa,GAAGzB,CAAI;AAAA,MACpB,SAAS,GAAG4B,CAAO;AAAA,MACnB,SAAS,GAAGC,CAAO;AAAA,MACnB,WAAWN;AAAA,MAEX,UAAA,gBAAAf,EAAC,SAAI,aAAU,8BAA6B,WAAWU,EAAGM,GAAYM,CAAkB,GACrF,UAAAH,EAAA,CACH;AAAA,IAAA;AAAA,EAAA,GAIEU,IACJ,gBAAA7B,EAAC4B,GAAA,EAAe,IAAG,WAAU,WAAWb,GACtC,UAAA,gBAAAf,EAAC,OAAA,EAAI,aAAU,4BAA2B,WAAWU,EAAGM,GAAYO,CAAgB,GACjF,UAAAvC,GACH,GACF;AAGF,SACE,gBAAAgB;AAAA,IAAC8B;AAAA,IAAA;AAAA,MAEC,aAAAN;AAAA,MACA,aAAU;AAAA,MACV,WAAWd,EAAG,kCAAkCD,CAAS;AAAA,MACzD,iBAAiB,CAACsB,MAAW;AAC3B,cAAMC,IAAMD,EAAOd,CAAkB;AACrC,QAAI,OAAOe,KAAQ,YAAUlC,EAAQkC,CAAG;AAAA,MAC1C;AAAA,MAEC,cACC,gBAAAC,EAAAC,GAAA,EACG,UAAA;AAAA,QAAAP;AAAA,QACD,gBAAA3B,EAACmC,GAAA,EAAgB,YAAU,GAAA,CAAC;AAAA,QAC3BN;AAAA,MAAA,EAAA,CACH,IAEA,gBAAAI,EAAAC,GAAA,EACG,UAAA;AAAA,QAAAL;AAAA,QACD,gBAAA7B,EAACmC,GAAA,EAAgB,YAAU,GAAA,CAAC;AAAA,QAC3BR;AAAA,MAAA,EAAA,CACH;AAAA,IAAA;AAAA,IApBGrC;AAAA,EAAA;AAwBX;"}
1
+ {"version":3,"file":"AssistantLayout.js","sources":["../../../../src/components/composed/AssistantLayout/AssistantLayout.tsx"],"sourcesContent":["\"use client\"\n\nimport { PanelBottom, PanelLeft, PanelRight, X } from \"lucide-react\"\nimport * as React from \"react\"\n\nimport { dockPanels, type AssistantDock } from \"./dockLayout\"\n\nimport { Button } from \"@/components/ui/button\"\nimport {\n ResizableHandle,\n ResizablePanel,\n ResizablePanelGroup,\n} from \"@/components/ui/resizable\"\nimport { cn } from \"@/lib/utils\"\n\n// ---------------------------------------------------------------------------\n// Context + provider\n// ---------------------------------------------------------------------------\n\ninterface AssistantLayoutContextValue {\n /** Where the assistant docks. Persisted. */\n dock: AssistantDock\n setDock: (dock: AssistantDock) => void\n /** Assistant size as a percentage of the layout along the dock axis. Persisted. */\n size: number\n setSize: (size: number) => void\n /** Whether the assistant is shown. In-memory by default (resets to visible on reload). */\n visible: boolean\n setVisible: (visible: boolean) => void\n}\n\nconst AssistantLayoutContext = React.createContext<AssistantLayoutContextValue | null>(null)\n\nexport interface AssistantLayoutProviderProps {\n children: React.ReactNode\n /** localStorage key prefix for the persisted dock + size. */\n storageKey?: string\n /** Default dock when nothing is persisted. */\n defaultDock?: AssistantDock\n /** Default assistant size as a percentage (1–99) of the layout. */\n defaultSize?: number\n /** Whether the assistant starts visible. */\n defaultVisible?: boolean\n /** Persist dock + size to localStorage. Defaults to `true`. */\n persist?: boolean\n}\n\nfunction readDock(key: string, fallback: AssistantDock): AssistantDock {\n if (typeof window === \"undefined\") return fallback\n const v = window.localStorage.getItem(`${key}.dock`)\n return v === \"right\" || v === \"bottom\" || v === \"left\" ? v : fallback\n}\n\nfunction readSize(key: string, fallback: number): number {\n if (typeof window === \"undefined\") return fallback\n const v = Number(window.localStorage.getItem(`${key}.size`))\n // Persisted as a percentage; ignore anything outside the open (0, 100) range.\n if (!Number.isFinite(v) || v <= 0 || v >= 100) return fallback\n return v\n}\n\nexport function AssistantLayoutProvider({\n children,\n storageKey = \"ts-ui.assistant\",\n defaultDock = \"left\",\n defaultSize = 32,\n defaultVisible = true,\n persist = true,\n}: AssistantLayoutProviderProps) {\n const [dock, setDockState] = React.useState<AssistantDock>(() =>\n persist ? readDock(storageKey, defaultDock) : defaultDock\n )\n const [size, setSizeState] = React.useState<number>(() =>\n persist ? readSize(storageKey, defaultSize) : defaultSize\n )\n const [visible, setVisible] = React.useState(defaultVisible)\n\n const setDock = React.useCallback(\n (next: AssistantDock) => {\n setDockState(next)\n if (persist && typeof window !== \"undefined\")\n window.localStorage.setItem(`${storageKey}.dock`, next)\n },\n [storageKey, persist]\n )\n\n const setSize = React.useCallback(\n (next: number) => {\n setSizeState(next)\n if (persist && typeof window !== \"undefined\")\n window.localStorage.setItem(`${storageKey}.size`, String(Math.round(next)))\n },\n [storageKey, persist]\n )\n\n const value = React.useMemo(\n () => ({ dock, setDock, size, setSize, visible, setVisible }),\n [dock, setDock, size, setSize, visible]\n )\n\n return <AssistantLayoutContext.Provider value={value}>{children}</AssistantLayoutContext.Provider>\n}\n\nexport function useAssistantLayout(): AssistantLayoutContextValue {\n const ctx = React.useContext(AssistantLayoutContext)\n if (!ctx) throw new Error(\"useAssistantLayout must be used within an AssistantLayoutProvider\")\n return ctx\n}\n\n// ---------------------------------------------------------------------------\n// Dock controls (segmented icon control for a top bar)\n// ---------------------------------------------------------------------------\n\nconst DOCK_OPTIONS: { value: AssistantDock; label: string; Icon: typeof PanelLeft }[] = [\n { value: \"left\", label: \"Dock assistant left\", Icon: PanelLeft },\n { value: \"bottom\", label: \"Dock assistant bottom\", Icon: PanelBottom },\n { value: \"right\", label: \"Dock assistant right\", Icon: PanelRight },\n]\n\nexport interface AssistantDockControlsProps {\n /** Label shown before the icons. Pass `null` to hide it. */\n label?: React.ReactNode\n className?: string\n}\n\n/**\n * Segmented control of dock icons. Clicking an inactive icon docks + shows the\n * assistant there; clicking the active icon again hides it.\n */\nexport function AssistantDockControls({ label = \"AI Assistant\", className }: AssistantDockControlsProps) {\n const { dock, setDock, visible, setVisible } = useAssistantLayout()\n\n return (\n <div className={cn(\"flex items-center gap-2\", className)}>\n {label != null && <span className=\"text-sm font-medium\">{label}</span>}\n <div className=\"inline-flex overflow-hidden rounded-lg border border-border\">\n {DOCK_OPTIONS.map(({ value, label: optionLabel, Icon }) => {\n const active = visible && dock === value\n return (\n <Button\n key={value}\n variant={active ? \"secondary\" : \"ghost\"}\n size=\"icon-sm\"\n // bg-clip-border so the filled (active/hover) state reaches the\n // cell edge instead of leaving a 1px gap from the button's\n // transparent border + default bg-clip-padding.\n className=\"rounded-none bg-clip-border\"\n aria-label={active ? \"Hide AI Assistant\" : optionLabel}\n aria-pressed={active}\n title={active ? \"Hide AI Assistant\" : optionLabel}\n onClick={() => {\n if (active) setVisible(false)\n else {\n setDock(value)\n setVisible(true)\n }\n }}\n >\n <Icon className=\"size-4\" />\n </Button>\n )\n })}\n </div>\n </div>\n )\n}\n\n// ---------------------------------------------------------------------------\n// Layout body\n// ---------------------------------------------------------------------------\n\n// Each panel is padded so the resize handle sits in a comfortable gutter between\n// the cards rather than a hairline seam (SW-2096). The padding lives inside the\n// panel box, so react-resizable-panels' flex sizing is unaffected.\nconst PANEL_PAD = \"flex min-h-0 min-w-0 p-2\"\n// The visible card surface rendered inside each panel.\nconst CARD_CLASS =\n \"flex h-full min-h-0 min-w-0 flex-1 flex-col overflow-hidden rounded-lg border border-border bg-card\"\n\nconst ASSISTANT_PANEL_ID = \"assistant\"\n\nexport interface AssistantLayoutProps {\n /** The AI Assistant panel content (e.g. a `<Chat />`). */\n assistant: React.ReactNode\n /** The main content; fills the remaining space (and the whole body when the assistant is hidden). */\n children: React.ReactNode\n /**\n * Title for the assistant panel's header cap (SW-2592). When set, the panel\n * renders a tinted (`bg-accent`) header band above `assistant` — the thing\n * that makes the assistant panel read as distinct from the content panel\n * (both are otherwise the same `bg-card` card). Omit to keep the panel a plain\n * card whose chrome you supply inside `assistant` (backward compatible).\n */\n assistantTitle?: React.ReactNode\n /** Optional element before the title in the header cap (e.g. an icon). */\n assistantIcon?: React.ReactNode\n /** Extra elements in the header cap, before the close button. */\n assistantHeaderActions?: React.ReactNode\n /** Render a close button in the header cap that hides the panel. Defaults to `true` when `assistantTitle` is set. */\n showAssistantClose?: boolean\n /** Min assistant size as a percentage of the layout. */\n minSize?: number\n /** Max assistant size as a percentage of the layout. */\n maxSize?: number\n className?: string\n assistantClassName?: string\n contentClassName?: string\n}\n\n/**\n * Docks the assistant left / right / bottom of the main content and resizes it\n * with the design-system `Resizable` (react-resizable-panels). Must be rendered\n * inside an `AssistantLayoutProvider`; pair with `AssistantDockControls`.\n *\n * The group is keyed by `dock`, so changing dock remounts the panels. The\n * assistant panel is therefore re-created on redock (its transient state is not\n * preserved across a dock change) — a deliberate trade-off for using the shared\n * resizable primitive rather than a bespoke splitter.\n */\nexport function AssistantLayout({\n assistant,\n children,\n assistantTitle,\n assistantIcon,\n assistantHeaderActions,\n showAssistantClose,\n minSize = 20,\n maxSize = 70,\n className,\n assistantClassName,\n contentClassName,\n}: AssistantLayoutProps) {\n const { dock, size, setSize, visible, setVisible } = useAssistantLayout()\n const { orientation, assistantFirst } = dockPanels(dock)\n\n // Accent header cap — the assistant panel's brand band. Only rendered when a\n // title is provided; content panel never gets one, so the two panels read as\n // distinct even though both are `bg-card` (SW-2592).\n const showClose = showAssistantClose ?? assistantTitle != null\n const assistantHeader = assistantTitle != null && (\n <div\n data-slot=\"assistant-layout-assistant-header\"\n className=\"flex shrink-0 items-center gap-2 border-b border-primary/15 bg-accent px-3 py-2\"\n >\n {assistantIcon != null && <span className=\"flex shrink-0 items-center justify-center\">{assistantIcon}</span>}\n <span className=\"min-w-0 flex-1 truncate text-sm font-semibold text-foreground\">{assistantTitle}</span>\n {assistantHeaderActions}\n {showClose && (\n <Button\n variant=\"ghost\"\n size=\"icon-sm\"\n className=\"text-muted-foreground\"\n aria-label=\"Hide assistant\"\n onClick={() => setVisible(false)}\n >\n <X />\n </Button>\n )}\n </div>\n )\n\n // Hidden: no resizable group, content fills the whole body.\n if (!visible) {\n return (\n <div\n data-slot=\"assistant-layout\"\n className={cn(\"flex min-h-0 flex-1 overflow-hidden\", className)}\n >\n {/* flex-1 so the lone content panel fills the width (the ResizablePanel\n self-sizes when visible; this plain div needs to be told to grow).\n Padded to match the inset the visible panels carry. */}\n <div className={cn(PANEL_PAD, \"flex-1\")}>\n <div data-slot=\"assistant-layout-content\" className={cn(CARD_CLASS, contentClassName)}>\n {children}\n </div>\n </div>\n </div>\n )\n }\n\n const assistantPanel = (\n <ResizablePanel\n id={ASSISTANT_PANEL_ID}\n defaultSize={`${size}%`}\n minSize={`${minSize}%`}\n maxSize={`${maxSize}%`}\n className={PANEL_PAD}\n >\n <div data-slot=\"assistant-layout-assistant\" className={cn(CARD_CLASS, assistantClassName)}>\n {assistantHeader}\n {assistant}\n </div>\n </ResizablePanel>\n )\n\n const contentPanel = (\n <ResizablePanel id=\"content\" className={PANEL_PAD}>\n <div data-slot=\"assistant-layout-content\" className={cn(CARD_CLASS, contentClassName)}>\n {children}\n </div>\n </ResizablePanel>\n )\n\n return (\n <ResizablePanelGroup\n key={dock}\n orientation={orientation}\n data-slot=\"assistant-layout\"\n className={cn(\"min-h-0 flex-1 overflow-hidden\", className)}\n onLayoutChanged={(layout) => {\n const pct = layout[ASSISTANT_PANEL_ID]\n if (typeof pct === \"number\") setSize(pct)\n }}\n >\n {assistantFirst ? (\n <>\n {assistantPanel}\n <ResizableHandle withHandle />\n {contentPanel}\n </>\n ) : (\n <>\n {contentPanel}\n <ResizableHandle withHandle />\n {assistantPanel}\n </>\n )}\n </ResizablePanelGroup>\n )\n}\n"],"names":["AssistantLayoutContext","React","readDock","key","fallback","v","readSize","AssistantLayoutProvider","children","storageKey","defaultDock","defaultSize","defaultVisible","persist","dock","setDockState","size","setSizeState","visible","setVisible","setDock","next","setSize","value","jsx","useAssistantLayout","ctx","DOCK_OPTIONS","PanelLeft","PanelBottom","PanelRight","AssistantDockControls","label","className","cn","optionLabel","Icon","active","Button","PANEL_PAD","CARD_CLASS","ASSISTANT_PANEL_ID","AssistantLayout","assistant","assistantTitle","assistantIcon","assistantHeaderActions","showAssistantClose","minSize","maxSize","assistantClassName","contentClassName","orientation","assistantFirst","dockPanels","showClose","assistantHeader","jsxs","X","assistantPanel","ResizablePanel","contentPanel","ResizablePanelGroup","layout","pct","Fragment","ResizableHandle"],"mappings":"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"}