@brainfish-ai/components 0.28.3 → 0.28.5

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,4 +1,4 @@
1
- import e,{useContext as a,useState as t,useMemo as r,useRef as n,useEffect as l,useCallback as i,isValidElement as o}from"react";import{useMediaQuery as s}from"usehooks-ts";import{a as d,H as c}from"./header-nav.C9r4A44a.js";import{cva as u}from"class-variance-authority";import{c as m}from"./utils.C6Qu-kwd.js";import{ScrollArea as h}from"../components/ui/scroll-area.js";import{F as f}from"./feature-flags.DOcVlPHk.js";import{Item as v}from"../components/ui/item.js";import{S as g}from"./sidebar.BdJe6AhO.js";const p=e.createContext(null),b=e.createContext(null);function w({value:a,children:t}){/* @__PURE__ */
1
+ import e,{useContext as a,useState as t,useMemo as r,useRef as n,useEffect as l,useCallback as i,isValidElement as o}from"react";import{useMediaQuery as s}from"usehooks-ts";import{a as d,H as c}from"./header-nav.C9r4A44a.js";import{cva as u}from"class-variance-authority";import{c as m}from"./utils.C6Qu-kwd.js";import{ScrollArea as h}from"../components/ui/scroll-area.js";import{F as f}from"./feature-flags.DOcVlPHk.js";import{Item as v}from"../components/ui/item.js";import{S as g}from"./sidebar.HOrQaimG.js";const p=e.createContext(null),b=e.createContext(null);function w({value:a,children:t}){/* @__PURE__ */
2
2
  return e.createElement(b.Provider,{value:a},t)}function y(){return e.useContext(b)}function N(){const a=e.useContext(b);if(!a)throw new Error("useRightSidebar must be used within a <FullLayout> component.");return{isOpen:a.isRightSidebarOpen,open:a.openRightSidebar,close:a.closeRightSidebar,toggle:a.toggleRightSidebar}}function E({children:a}){/* @__PURE__ */
3
3
  return e.createElement(e.Fragment,null,a)}function S({children:a}){/* @__PURE__ */
4
4
  return e.createElement(e.Fragment,null,a)}function x(a){const{onBrainfishNativeClick:t,...r}=a,n=y();if(!n)return null;/* @__PURE__ */
@@ -17,4 +17,4 @@ return e.createElement(f,{flags:t},/* @__PURE__ */e.createElement(I,{...r}))},{M
17
17
  /* @__PURE__ */e.createElement("svg",{className:"size-6",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},/* @__PURE__ */e.createElement("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M4 6h16M4 12h16M4 18h16"}))),
18
18
  /* @__PURE__ */e.createElement("div",{"data-slot":"full-layout-header-center",className:"flex-1 min-w-0"},n),null!=t&&/* @__PURE__ */e.createElement("div",{"data-slot":"full-layout-header-trigger-right",className:"ml-auto"},/* @__PURE__ */e.createElement("button",{type:"button",onClick:t,className:"p-2 hover:bg-gray-100 rounded-lg transition-colors","aria-label":"Toggle chat"},
19
19
  /* @__PURE__ */e.createElement("svg",{className:"size-6",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},/* @__PURE__ */e.createElement("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M8 10h.01M12 10h.01M16 10h.01M9 16H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-5l-5 5v-5z"}))))));B.displayName="FullLayoutHeader";export{j as F,B as a,R as b,p as c,w as d,k as e,N as f,y as u};
20
- //# sourceMappingURL=header-pane.BOdI3pqC.js.map
20
+ //# sourceMappingURL=header-pane.1-3lMndU.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"header-pane.BOdI3pqC.js","sources":["../../../src/layouts/full-layout/context.tsx","../../../src/layouts/full-layout/components/main-area.tsx","../../../src/layouts/full-layout/components/body.tsx","../../../src/layouts/full-layout/components/header.tsx","../../../src/layouts/full-layout/left-sidebar-pane.tsx","../../../src/layouts/full-layout/components/left-sidebar.tsx","../../../src/layouts/full-layout/components/main.tsx","../../../src/layouts/full-layout/right-sidebar-pane.tsx","../../../src/layouts/full-layout/components/right-sidebar.tsx","../../../src/layouts/full-layout/blurry-blob.tsx","../../../src/layouts/full-layout/layout.tsx","../../../src/layouts/full-layout/header-pane.tsx"],"sourcesContent":["import React from 'react';\n\n/** Nav state derived from route (e.g. active ids). Provided by Platform; when null, layout uses props only. */\nexport interface FullLayoutNavState {\n appNavActiveId?: string;\n sectionNavActiveId?: string;\n activeArticleId?: string;\n}\n\nconst FullLayoutNavStateContext = React.createContext<FullLayoutNavState | null>(null);\n\nexport { FullLayoutNavStateContext };\n\nexport interface FullLayoutContextValue {\n isSideNavOpen: boolean;\n isRightSidebarOpen: boolean;\n toggleSidebar: () => void;\n openRightSidebar: () => void;\n closeRightSidebar: () => void;\n toggleRightSidebar: () => void;\n showSidenav: () => void;\n disableLeftSideNav: boolean;\n leftNavWidth: number;\n isMobile: boolean;\n sideNavRef: React.RefObject<HTMLDivElement | null>;\n rightSidebarRef: React.RefObject<HTMLElement | null>;\n sidebarToggleRef: React.RefObject<HTMLButtonElement | null>;\n handleResizeStart: (e: React.MouseEvent) => void;\n handleResizeKeyDown: (e: React.KeyboardEvent) => void;\n ariaValuenow: number;\n ariaValuemin: number;\n ariaValuemax: number;\n /** Mirrors `FullLayout` prop; `FullLayout.Main` uses it for viewport height when Radix ScrollArea is off. */\n disableMainScrollArea: boolean;\n}\n\nconst FullLayoutContext = React.createContext<FullLayoutContextValue | null>(null);\n\nexport interface FullLayoutProviderProps {\n value: FullLayoutContextValue;\n children: React.ReactNode;\n}\n\nexport function FullLayoutProvider({ value, children }: FullLayoutProviderProps) {\n return <FullLayoutContext.Provider value={value}>{children}</FullLayoutContext.Provider>;\n}\n\nexport function useFullLayoutContext(): FullLayoutContextValue | null {\n return React.useContext(FullLayoutContext);\n}\n\nexport interface UseRightSidebarReturn {\n /** Whether the right sidebar is currently open. */\n isOpen: boolean;\n /** Open the right sidebar (no-op if already open). */\n open: () => void;\n /** Close the right sidebar (no-op if already closed). */\n close: () => void;\n /** Toggle the right sidebar open/closed. */\n toggle: () => void;\n}\n\n/**\n * Convenience hook for programmatically controlling the right sidebar.\n *\n * Must be used inside a `<FullLayout>` tree.\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const rightSidebar = useRightSidebar();\n * return <button onClick={rightSidebar.open}>Open sidebar</button>;\n * }\n * ```\n */\nexport function useRightSidebar(): UseRightSidebarReturn {\n const ctx = React.useContext(FullLayoutContext);\n if (!ctx) {\n throw new Error('useRightSidebar must be used within a <FullLayout> component.');\n }\n\n return {\n isOpen: ctx.isRightSidebarOpen,\n open: ctx.openRightSidebar,\n close: ctx.closeRightSidebar,\n toggle: ctx.toggleRightSidebar,\n };\n}\n","import React from 'react';\n\nexport function MainArea({ children }: { children?: React.ReactNode }) {\n return <>{children}</>;\n}\nMainArea.displayName = 'FullLayout.MainArea';\n","import React from 'react';\n\nexport function Body({ children }: { children?: React.ReactNode }) {\n return <>{children}</>;\n}\nBody.displayName = 'FullLayout.Body';\n","import React, { ComponentProps } from 'react';\n\nimport { HeaderNav } from '../../header-nav';\nimport { useFullLayoutContext } from '../context';\n\nexport function Header(props: ComponentProps<typeof HeaderNav>) {\n const { onBrainfishNativeClick, ...rest } = props;\n const ctx = useFullLayoutContext();\n if (!ctx) return null;\n\n const handleNativeClick = () => {\n ctx.toggleRightSidebar();\n onBrainfishNativeClick?.();\n };\n\n return (\n <HeaderNav\n {...rest}\n showSidebarToggle={!ctx.disableLeftSideNav}\n isSideNavOpen={ctx.isSideNavOpen}\n onSideNavigationToggle={ctx.toggleSidebar}\n onBrainfishNativeClick={handleNativeClick}\n sidebarToggleRef={ctx.sidebarToggleRef as React.Ref<HTMLButtonElement>}\n />\n );\n}\nHeader.displayName = 'FullLayout.Header';\n","import React, { ComponentProps } from 'react';\n\nimport { Sidebar } from '../sidebar';\n\nimport { cn } from '@/lib/utils';\n\nexport interface FullLayoutLeftSidebarProps extends Omit<React.ComponentPropsWithoutRef<'div'>, 'children'> {\n open: boolean;\n widthPx: number;\n onResizeStart: (e: React.MouseEvent) => void;\n onResizeKeyDown: (e: React.KeyboardEvent) => void;\n ariaValuenow: number;\n ariaValuemin: number;\n ariaValuemax: number;\n sidebarProps: ComponentProps<typeof Sidebar>;\n}\n\nconst FullLayoutLeftSidebar = React.forwardRef<HTMLDivElement, FullLayoutLeftSidebarProps>(\n (\n {\n open,\n widthPx,\n onResizeStart,\n onResizeKeyDown,\n ariaValuenow,\n ariaValuemin,\n ariaValuemax,\n sidebarProps,\n className,\n ...props\n },\n ref,\n ) => {\n return (\n <div\n ref={ref}\n id=\"left-sidebar-pane\"\n data-slot=\"full-layout-left-sidebar\"\n tabIndex={-1}\n data-state={open ? 'open' : 'closed'}\n className={cn(\n 'min-w-0 overflow-hidden flex flex-col relative transition-[width] data-[state=closed]:w-0 data-[state=closed]:pointer-events-none data-[state=open]:w-full md:data-[state=open]:w-[var(--left-nav-width)]',\n className,\n )}\n style={{\n ['--left-nav-width' as string]: `${widthPx}px`,\n }}\n {...props}\n >\n <Sidebar\n {...sidebarProps}\n collapsed={!open}\n className=\"transition-[width] w-[var(--left-nav-width)] h-[calc(100dvh-var(--header-nav-height,0))]\"\n />\n\n {/* Window Splitter per APG: https://www.w3.org/ARIA/apg/patterns/windowsplitter/ */}\n {/* eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions -- focusable separator per APG Window Splitter pattern */}\n <div\n role=\"separator\"\n aria-orientation=\"vertical\"\n aria-valuenow={ariaValuenow}\n aria-valuemin={ariaValuemin}\n aria-valuemax={ariaValuemax}\n aria-label=\"Resize left sidebar\"\n aria-controls=\"left-sidebar-pane\"\n data-slot=\"full-layout-left-sidebar-resize-handle\"\n /* eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex -- focusable separator per APG Window Splitter pattern */\n tabIndex={0}\n onMouseDown={onResizeStart}\n onKeyDown={onResizeKeyDown}\n className=\"hidden lg:block absolute top-0 right-0 bottom-0 w-1 bg-transparent hover:bg-blue-500 cursor-ew-resize shrink-0 [&>div]:pointer-events-none\"\n >\n <div className=\"absolute inset-y-0 -right-1 w-3\" />\n </div>\n </div>\n );\n },\n);\n\nFullLayoutLeftSidebar.displayName = 'FullLayoutLeftSidebar';\n\nexport { FullLayoutLeftSidebar };\n","import React, { ComponentProps, useContext } from 'react';\n\nimport { Sidebar } from '../../sidebar';\nimport { FullLayoutNavStateContext, useFullLayoutContext } from '../context';\nimport { FullLayoutLeftSidebar } from '../left-sidebar-pane';\n\nexport function LeftSidebar(props: ComponentProps<typeof Sidebar>) {\n const ctx = useFullLayoutContext();\n const navState = useContext(FullLayoutNavStateContext);\n if (!ctx) return null;\n if (ctx.disableLeftSideNav) return null;\n\n const sidebarProps: ComponentProps<typeof Sidebar> =\n navState != null\n ? {\n ...props,\n appNavActiveId: navState.appNavActiveId ?? props.appNavActiveId,\n sectionNavActiveId: navState.sectionNavActiveId ?? props.sectionNavActiveId,\n activeArticleId: navState.activeArticleId ?? props.activeArticleId,\n }\n : props;\n\n return (\n <FullLayoutLeftSidebar\n ref={ctx.sideNavRef as React.Ref<HTMLDivElement>}\n open={ctx.isSideNavOpen}\n widthPx={ctx.leftNavWidth}\n onResizeStart={ctx.handleResizeStart}\n onResizeKeyDown={ctx.handleResizeKeyDown}\n ariaValuenow={ctx.ariaValuenow}\n ariaValuemin={ctx.ariaValuemin}\n ariaValuemax={ctx.ariaValuemax}\n sidebarProps={sidebarProps}\n />\n );\n}\nLeftSidebar.displayName = 'FullLayout.LeftSidebar';\n","import React from 'react';\n\nimport { useFullLayoutContext } from '../context';\n\nimport { Item } from '@/components/ui/item';\nimport { cn } from '@/lib/utils';\n\nexport function Main({ children, className }: { children?: React.ReactNode; className?: string }) {\n const ctx = useFullLayoutContext();\n const mainIsScrollContainer = ctx?.disableMainScrollArea ?? false;\n\n return (\n <Item\n className={cn(\n 'p-0',\n mainIsScrollContainer &&\n 'h-[calc(100dvh-var(--header-nav-height))] md:h-[calc(100dvh-var(--header-nav-height)-1rem)] min-h-0 overflow-y-auto p-4 md:p-8',\n className,\n )}\n >\n {children}\n </Item>\n );\n}\nMain.displayName = 'FullLayout.Main';\n","import React from 'react';\n\nimport { cn } from '@/lib/utils';\nimport { ScrollArea } from '@/components/ui/scroll-area';\n\nexport interface FullLayoutRightSidebarProps extends Omit<React.ComponentPropsWithoutRef<'aside'>, 'children'> {\n open: boolean;\n children: React.ReactNode;\n scrollable?: boolean;\n}\n\nconst FullLayoutRightSidebar = React.forwardRef<HTMLElement, FullLayoutRightSidebarProps>(\n ({ open, scrollable = true, className, children, ...props }, ref) => {\n return (\n <aside\n ref={ref as React.Ref<HTMLDivElement>}\n data-slot=\"full-layout-right-sidebar\"\n data-state={open ? 'open' : 'closed'}\n className={cn(\n 'bg-background shadow-lg flex flex-col',\n 'fixed h-[calc(100dvh-var(--header-nav-height))] z-10 w-screen transition-transform duration-300 ease-in-out data-[state=closed]:translate-x-full data-[state=open]:translate-x-0',\n 'md:relative md:h-dvh md:w-96 md:top-0',\n className,\n )}\n {...props}\n >\n <div className=\"flex flex-col flex-1 min-h-0 overflow-hidden\" data-slot=\"full-layout-right-sidebar-content\">\n {scrollable ? (\n <ScrollArea className=\"h-[calc(100dvh-var(--header-nav-height))] md:h-dvh\">{children}</ScrollArea>\n ) : (\n children\n )}\n </div>\n </aside>\n );\n },\n);\n\nFullLayoutRightSidebar.displayName = 'FullLayoutRightSidebar';\n\nexport { FullLayoutRightSidebar };\n","import React from 'react';\n\nimport { useFullLayoutContext } from '../context';\nimport { FullLayoutRightSidebar } from '../right-sidebar-pane';\n\nexport function RightSidebar({ children, scrollable }: { children?: React.ReactNode; scrollable?: boolean }) {\n const ctx = useFullLayoutContext();\n if (!ctx) return null;\n\n return (\n <FullLayoutRightSidebar\n ref={ctx.rightSidebarRef as React.Ref<HTMLElement>}\n open={ctx.isRightSidebarOpen}\n scrollable={scrollable}\n className=\"top-[var(--header-nav-height)]\"\n >\n {children}\n </FullLayoutRightSidebar>\n );\n}\nRightSidebar.displayName = 'FullLayout.RightSidebar';\n","import React from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\n\nimport { cn } from '@/lib/utils';\n\nconst blurryBlob = cva('blurry-blob', {\n variants: {\n variant: {\n topLeft: '',\n bottomRight: '!top-auto !left-auto !-bottom-[10%] !right-0 rotate-180',\n },\n },\n defaultVariants: {\n variant: 'topLeft',\n },\n});\n\ninterface BlurryBlobProps extends VariantProps<typeof blurryBlob> {\n className?: string;\n}\n\nexport const GooFilter = () => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"fixed top-0 left-0 w-0 h-0\">\n <defs>\n <filter id=\"goo\">\n <feGaussianBlur in=\"SourceGraphic\" stdDeviation=\"10\" result=\"blur\" />\n <feColorMatrix in=\"blur\" mode=\"matrix\" values=\"1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 18 -8\" result=\"goo\" />\n <feBlend in=\"SourceGraphic\" in2=\"goo\" />\n </filter>\n </defs>\n </svg>\n);\n\nconst BlurryBlob = ({ className, variant }: BlurryBlobProps) => {\n return (\n <div className={cn(blurryBlob({ variant }), className)}>\n <div className=\"gradients-container\">\n <div className=\"g1\" />\n <div className=\"g2\" />\n <div className=\"g3\" />\n <div className=\"g4\" />\n </div>\n </div>\n );\n};\n\nexport default BlurryBlob;\n","import React, { useState, useRef, useEffect, useCallback, isValidElement, useMemo } from 'react';\nimport { useMediaQuery } from 'usehooks-ts';\n\nimport { FullLayoutProvider } from './context';\nimport { HEADER_NAV_HEIGHT } from '../header-nav';\nimport * as Compounds from './components';\nimport BlurryBlob, { GooFilter } from './blurry-blob';\n\nimport { ScrollArea } from '@/components/ui/scroll-area';\nimport { FeatureFlagProvider } from '@/lib/feature-flags';\nimport type { FeatureFlags } from '@/lib/feature-flags';\nimport { cn } from '@/lib/utils';\n\nconst MIN_SIDENAV_WIDTH = 260;\nconst CLOSE_SIDENAV_THRESHOLD = MIN_SIDENAV_WIDTH - 32;\nconst MAX_SIDENAV_WIDTH = 600;\nconst RIGHT_SIDEBAR_WIDTH = 384;\n\nexport interface FullLayoutRootProps {\n children?: React.ReactNode;\n disableLeftSideNav?: boolean;\n /** When true, main column uses a plain div (no Radix ScrollArea); viewport height is applied on `FullLayout.Main`. */\n disableMainScrollArea?: boolean;\n className?: string;\n /** When true, the right sidebar is always open and cannot be toggled. */\n forceRightSidebarOpen?: boolean;\n}\n\n// Helper function to extract slots from children\nfunction extractSlots<T extends Record<string, React.ComponentType<any>>>(\n children: React.ReactNode,\n refs: T,\n): { [K in keyof T]: React.ReactElement | null } {\n const out = {} as { [K in keyof T]: React.ReactElement | null };\n const arr = React.Children.toArray(children);\n for (const key of Object.keys(refs) as (keyof T)[]) {\n const match = arr.find((c): c is React.ReactElement => isValidElement(c) && c.type === refs[key]);\n out[key] = match ?? null;\n }\n\n return out;\n}\n\n// --- Root component ---\n\nfunction FullLayoutRoot({\n children,\n disableLeftSideNav = false,\n disableMainScrollArea = false,\n className,\n forceRightSidebarOpen = false,\n}: FullLayoutRootProps) {\n // Match isMobile breakpoint (max-width: 767px) so no flash on 768–1023px\n const [isSideNavOpen, setIsSideNavOpen] = useState(() => typeof window !== 'undefined' && window.innerWidth > 767);\n const [isRightSidebarOpen, setIsRightSidebarOpen] = useState(forceRightSidebarOpen);\n const [isResizing, setIsResizing] = useState(false);\n const [gridWidth, setGridWidth] = useState(() => (typeof window !== 'undefined' ? window.innerWidth : 0));\n\n const newMinNavWidth = useMemo(\n () =>\n gridWidth > 0\n ? Math.max(MIN_SIDENAV_WIDTH, Math.min(MAX_SIDENAV_WIDTH, Math.round(gridWidth * 0.18)))\n : MIN_SIDENAV_WIDTH,\n [gridWidth],\n );\n const [leftNavWidth, setLeftNavWidth] = useState(newMinNavWidth);\n\n const sideNavRef = useRef<HTMLDivElement>(null);\n const rightSidebarRef = useRef<HTMLElement>(null);\n const sidebarToggleRef = useRef<HTMLButtonElement>(null);\n const gridRef = useRef<HTMLDivElement>(null);\n const prevSideNavOpenRef = useRef(isSideNavOpen);\n const resizeAcRef = useRef<AbortController | null>(null);\n const isMobile = useMediaQuery('(max-width: 767px)');\n const isWideDesktop = useMediaQuery('(min-width: 1280px)');\n\n // Prevent native scrollbar from appearing\n useEffect(() => {\n if (!document.body.querySelector('.sbdocs')) {\n document.body.style.overflow = 'hidden';\n }\n\n return () => {\n document.body.style.overflow = '';\n };\n }, []);\n\n // Handle grid width changes\n useEffect(() => {\n const el = gridRef.current;\n if (!el) return;\n\n const ro = new ResizeObserver(([entry]) => {\n setGridWidth(entry.contentRect.width);\n });\n ro.observe(el);\n\n return () => ro.disconnect();\n }, []);\n\n // Close other sidebar if opening a new one on wide desktop\n const closeOtherSidebar = useCallback(\n (opening: 'left' | 'right') => {\n if (isWideDesktop) return;\n if (opening === 'left') setIsRightSidebarOpen(false);\n else setIsSideNavOpen(false);\n },\n [isWideDesktop],\n );\n\n // Show left sidebar\n const showSidenav = useCallback(() => {\n closeOtherSidebar('left');\n setIsSideNavOpen(true);\n setLeftNavWidth(newMinNavWidth);\n sideNavRef.current?.focus();\n }, [closeOtherSidebar, newMinNavWidth]);\n\n // Toggle left sidebar\n const toggleSidebar = useCallback(() => {\n closeOtherSidebar('left');\n setIsSideNavOpen((prev) => !prev);\n }, [closeOtherSidebar]);\n\n // Open right sidebar (no-op if already open)\n const openRightSidebar = useCallback(() => {\n closeOtherSidebar('right');\n setIsRightSidebarOpen(true);\n }, [closeOtherSidebar]);\n\n // Close right sidebar (no-op if already closed)\n const closeRightSidebar = useCallback(() => {\n setIsRightSidebarOpen(false);\n }, []);\n\n // Toggle right sidebar\n const toggleRightSidebar = useCallback(() => {\n if (forceRightSidebarOpen) return;\n closeOtherSidebar('right');\n setIsRightSidebarOpen((prev) => !prev);\n }, [closeOtherSidebar, forceRightSidebarOpen]);\n\n // Apply left nav width - used for resizing left sidebar\n const applyLeftNavWidth = useCallback(\n (newWidth: number): boolean => {\n if (newWidth < CLOSE_SIDENAV_THRESHOLD) {\n setLeftNavWidth(newMinNavWidth);\n setIsSideNavOpen(false);\n\n return true;\n } else {\n // clamp to MAX_SIDENAV_WIDTH\n setLeftNavWidth(Math.min(MAX_SIDENAV_WIDTH, newWidth));\n\n return false;\n }\n },\n [newMinNavWidth],\n );\n\n // Handle resize start\n const handleResizeStart = useCallback((e: React.MouseEvent) => {\n e.preventDefault();\n resizeAcRef.current = new AbortController();\n setIsResizing(true);\n }, []);\n\n // Handle resize end\n const endResize = useCallback(() => {\n setIsResizing(false);\n document.body.style.cursor = '';\n document.body.style.userSelect = '';\n }, []);\n\n // Handle mouse move during resize\n const handleMouseMove = useCallback(\n (e: MouseEvent) => {\n if (!isResizing) return;\n if (applyLeftNavWidth(e.clientX)) {\n endResize();\n }\n },\n [isResizing, applyLeftNavWidth, endResize],\n );\n\n // Handle mouse up during resize\n const handleMouseUp = useCallback(() => endResize(), [endResize]);\n\n // Set inert attribute on side nav and right sidebar - disables tabbing to elements inside when sidebar is closed\n const setInert = useCallback((el: HTMLElement | null, open: boolean) => {\n if (!el) return;\n if (open) el.removeAttribute('inert');\n else el.setAttribute('inert', '');\n }, []);\n\n useEffect(() => {\n setInert(sideNavRef.current, isSideNavOpen);\n setInert(rightSidebarRef.current, isRightSidebarOpen);\n }, [isSideNavOpen, isRightSidebarOpen]);\n\n // Attach resize listeners when isResizing becomes true (controller already set in handleResizeStart)\n useEffect(() => {\n if (!isResizing || !resizeAcRef.current) return;\n\n const { signal } = resizeAcRef.current;\n document.body.style.cursor = 'ew-resize';\n document.body.style.userSelect = 'none';\n document.addEventListener('mousemove', handleMouseMove, { signal });\n document.addEventListener('mouseup', handleMouseUp, { signal });\n window.addEventListener('mouseup', handleMouseUp, { signal });\n setInert(sideNavRef.current, false);\n\n return () => {\n resizeAcRef.current?.abort();\n resizeAcRef.current = null;\n document.body.style.cursor = '';\n document.body.style.userSelect = '';\n setInert(sideNavRef.current, true);\n };\n }, [isResizing]);\n\n // Handle resize key down\n const handleResizeKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n const step = 16;\n if (e.key === 'ArrowLeft') {\n e.preventDefault();\n applyLeftNavWidth(leftNavWidth - step);\n } else if (e.key === 'ArrowRight') {\n e.preventDefault();\n applyLeftNavWidth(Math.min(MAX_SIDENAV_WIDTH, leftNavWidth + step));\n }\n },\n [leftNavWidth, applyLeftNavWidth],\n );\n\n const leftCol = disableLeftSideNav ? 0 : isSideNavOpen ? (isMobile ? gridWidth : leftNavWidth) : 0;\n const rightCol = isMobile ? 0 : isRightSidebarOpen ? RIGHT_SIDEBAR_WIDTH : 0;\n\n // Set left sidebar open state based on mobile\n useEffect(() => {\n setIsSideNavOpen(isMobile ? false : true);\n }, [isMobile]);\n\n // Focus sidebar toggle when left sidebar is closed\n useEffect(() => {\n if (prevSideNavOpenRef.current && !isSideNavOpen) {\n sidebarToggleRef.current?.focus();\n }\n prevSideNavOpenRef.current = isSideNavOpen;\n }, [isSideNavOpen]);\n\n const ariaRange = MAX_SIDENAV_WIDTH - newMinNavWidth;\n const ariaValuenow = ariaRange === 0 ? 100 : Math.round(((leftNavWidth - newMinNavWidth) / ariaRange) * 100);\n\n const layoutContextValue = useMemo(\n () => ({\n isSideNavOpen,\n isRightSidebarOpen,\n toggleSidebar,\n openRightSidebar,\n closeRightSidebar,\n toggleRightSidebar,\n showSidenav,\n disableLeftSideNav: disableLeftSideNav ?? false,\n leftNavWidth,\n isMobile,\n sideNavRef,\n rightSidebarRef,\n sidebarToggleRef,\n handleResizeStart,\n handleResizeKeyDown,\n ariaValuenow,\n ariaValuemin: 0,\n ariaValuemax: 100,\n disableMainScrollArea,\n }),\n [\n isSideNavOpen,\n isRightSidebarOpen,\n toggleSidebar,\n openRightSidebar,\n closeRightSidebar,\n toggleRightSidebar,\n showSidenav,\n leftNavWidth,\n isMobile,\n disableLeftSideNav,\n disableMainScrollArea,\n handleResizeStart,\n handleResizeKeyDown,\n ariaValuenow,\n ],\n );\n\n // --- Extract slots from children ---\n const { MainArea: mainArea, RightSidebar: rightSidebar } = extractSlots(children, {\n MainArea: Compounds.MainArea,\n RightSidebar: Compounds.RightSidebar,\n });\n const mainAreaChildren = isValidElement(mainArea)\n ? (mainArea.props as { children?: React.ReactNode }).children\n : null;\n const { Header: header, Body: body } = extractSlots(mainAreaChildren ?? null, {\n Header: Compounds.Header,\n Body: Compounds.Body,\n });\n const bodyChildren = isValidElement(body) ? (body.props as { children?: React.ReactNode }).children : null;\n const { LeftSidebar: leftSidebar, Main: main } = extractSlots(bodyChildren ?? null, {\n LeftSidebar: Compounds.LeftSidebar,\n Main: Compounds.Main,\n });\n\n const hasRightSidebar = rightSidebar != null;\n const mainPanelClasses =\n 'md:shadow-[2px_4px_12px_0_rgba(0,0,0,0.14)] md:dark:shadow-[2px_4px_12px_0_rgba(255,255,255,0.14)] md:rounded-lg';\n\n // --- Render the layout ---\n return (\n <FullLayoutProvider value={layoutContextValue}>\n <GooFilter />\n <BlurryBlob variant=\"topLeft\" />\n <BlurryBlob variant=\"bottomRight\" />\n <div\n className={cn(\n 'min-h-screen w-screen bg-background grid transition-[grid-template-columns] duration-300 ease-in-out',\n className,\n )}\n style={{\n gridTemplateColumns: hasRightSidebar ? 'minmax(0, 1fr) var(--right-col)' : 'minmax(0, 1fr)',\n ['--right-col' as string]: hasRightSidebar ? `${rightCol}px` : '0px',\n ['--header-nav-height' as string]: `${HEADER_NAV_HEIGHT}px`,\n }}\n >\n <div className=\"min-w-0 grid grid-rows-[auto_1fr]\">\n {header}\n\n <div\n ref={gridRef}\n data-sidenav-state={isSideNavOpen ? 'open' : 'closed'}\n data-right-sidebar-state={isRightSidebarOpen ? 'open' : 'closed'}\n className={cn(\n 'group/sidenav group/rightsidebar min-h-0 min-w-0 grid transition-[grid-template-columns] ease-linear',\n )}\n style={{\n gridTemplateColumns: `var(--left-col) minmax(0, 1fr)`,\n ['--left-col' as string]: `${leftCol}px`,\n }}\n >\n {disableLeftSideNav ? <div className=\"w-0\" /> : leftSidebar}\n <div className={cn('relative md:mr-4', { 'md:mx-4': !isSideNavOpen || disableLeftSideNav })}>\n {disableMainScrollArea ? (\n <div className={cn('bg-surface', mainPanelClasses)}>\n <main className=\"min-w-0 relative\">{main}</main>\n </div>\n ) : (\n <>\n <ScrollArea\n className={cn(\n 'bg-surface h-[calc(100dvh-var(--header-nav-height))] md:h-[calc(100dvh-var(--header-nav-height)-1rem)]',\n mainPanelClasses,\n )}\n >\n <div className=\"min-h-full\">\n <main className={cn('min-w-0 overflow-visible relative p-4 md:p-8')}>{main}</main>\n </div>\n </ScrollArea>\n <div\n aria-hidden\n className=\"main-scroll-fade pointer-events-none sticky bottom-4 left-0 right-0 h-16 bg-gradient-to-t from-surface to-transparent md:rounded-b-lg\"\n />\n </>\n )}\n </div>\n </div>\n </div>\n\n {hasRightSidebar ? rightSidebar : null}\n </div>\n </FullLayoutProvider>\n );\n}\n\n/**\n * Custom memo comparator: re-render only when these props change by reference/value.\n * Use this so changing other props (e.g. from a parent) does not force the layout shell to re-render.\n */\nfunction fullLayoutRootPropsAreEqual(prev: FullLayoutRootProps, next: FullLayoutRootProps): boolean {\n return (\n prev.children === next.children &&\n prev.className === next.className &&\n prev.disableLeftSideNav === next.disableLeftSideNav &&\n prev.disableMainScrollArea === next.disableMainScrollArea\n );\n}\n\nconst FullLayoutRootMemo = React.memo(FullLayoutRoot, fullLayoutRootPropsAreEqual);\n\nexport interface FullLayoutProps extends FullLayoutRootProps {\n /** Feature flags for layout/header (e.g. platform.brainfish-native.enabled). Passed through to FeatureFlagProvider. */\n featureFlags?: FeatureFlags;\n}\n\nfunction FullLayoutWithFlags(props: FullLayoutProps) {\n const { featureFlags, ...layoutProps } = props;\n\n return (\n <FeatureFlagProvider flags={featureFlags}>\n <FullLayoutRootMemo {...layoutProps} />\n </FeatureFlagProvider>\n );\n}\n\ntype FullLayoutCompound = typeof FullLayoutWithFlags & {\n MainArea: typeof Compounds.MainArea;\n Body: typeof Compounds.Body;\n Header: typeof Compounds.Header;\n LeftSidebar: typeof Compounds.LeftSidebar;\n Main: typeof Compounds.Main;\n RightSidebar: typeof Compounds.RightSidebar;\n};\n\nconst FullLayout: FullLayoutCompound = Object.assign(FullLayoutWithFlags, {\n MainArea: Compounds.MainArea,\n Body: Compounds.Body,\n Header: Compounds.Header,\n LeftSidebar: Compounds.LeftSidebar,\n Main: Compounds.Main,\n RightSidebar: Compounds.RightSidebar,\n});\n\nexport default FullLayout;\n","import React from 'react';\n\nimport { cn } from '@/lib/utils';\n\nexport interface FullLayoutHeaderProps extends React.ComponentPropsWithoutRef<'header'> {\n onOpenLeft?: () => void;\n onOpenRight?: () => void;\n}\n\nconst FullLayoutHeader = React.forwardRef<HTMLElement, FullLayoutHeaderProps>(\n ({ onOpenLeft, onOpenRight, className, children, ...props }, ref) => {\n return (\n <header\n ref={ref as React.Ref<HTMLHeadingElement>}\n data-slot=\"full-layout-header\"\n className={cn('h-16 bg-white shadow-md flex items-center px-4 shrink-0 sticky top-0 z-20', className)}\n {...props}\n >\n {onOpenLeft != null && (\n <button\n data-slot=\"full-layout-header-trigger-left\"\n type=\"button\"\n onClick={onOpenLeft}\n className=\"p-2 hover:bg-gray-100 rounded-lg transition-colors mr-4 lg:hidden\"\n aria-label=\"Toggle menu\"\n >\n <svg className=\"size-6\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M4 6h16M4 12h16M4 18h16\" />\n </svg>\n </button>\n )}\n <div data-slot=\"full-layout-header-center\" className=\"flex-1 min-w-0\">\n {children}\n </div>\n {onOpenRight != null && (\n <div data-slot=\"full-layout-header-trigger-right\" className=\"ml-auto\">\n <button\n type=\"button\"\n onClick={onOpenRight}\n className=\"p-2 hover:bg-gray-100 rounded-lg transition-colors\"\n aria-label=\"Toggle chat\"\n >\n <svg className=\"size-6\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M8 10h.01M12 10h.01M16 10h.01M9 16H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-5l-5 5v-5z\"\n />\n </svg>\n </button>\n </div>\n )}\n </header>\n );\n },\n);\n\nFullLayoutHeader.displayName = 'FullLayoutHeader';\n\nexport { FullLayoutHeader };\n"],"names":["FullLayoutNavStateContext","React","createContext","FullLayoutContext","FullLayoutProvider","value","children","createElement","Provider","useFullLayoutContext","useContext","useRightSidebar","ctx","Error","isOpen","isRightSidebarOpen","open","openRightSidebar","close","closeRightSidebar","toggle","toggleRightSidebar","MainArea","Body","Header","props","onBrainfishNativeClick","rest","HeaderNav","showSidebarToggle","disableLeftSideNav","isSideNavOpen","onSideNavigationToggle","toggleSidebar","sidebarToggleRef","displayName","FullLayoutLeftSidebar","forwardRef","widthPx","onResizeStart","onResizeKeyDown","ariaValuenow","ariaValuemin","ariaValuemax","sidebarProps","className","ref","id","tabIndex","cn","style","Sidebar","collapsed","role","onMouseDown","onKeyDown","LeftSidebar","navState","appNavActiveId","sectionNavActiveId","activeArticleId","sideNavRef","leftNavWidth","handleResizeStart","handleResizeKeyDown","Main","mainIsScrollContainer","disableMainScrollArea","Item","FullLayoutRightSidebar","scrollable","ScrollArea","RightSidebar","rightSidebarRef","blurryBlob","cva","variants","variant","topLeft","bottomRight","defaultVariants","GooFilter","xmlns","in","stdDeviation","result","mode","values","in2","BlurryBlob","MAX_SIDENAV_WIDTH","extractSlots","refs","out","arr","Children","toArray","key","Object","keys","match","find","c","isValidElement","type","FullLayoutRootMemo","memo","forceRightSidebarOpen","setIsSideNavOpen","useState","window","innerWidth","setIsRightSidebarOpen","isResizing","setIsResizing","gridWidth","setGridWidth","newMinNavWidth","useMemo","Math","max","min","round","setLeftNavWidth","useRef","gridRef","prevSideNavOpenRef","resizeAcRef","isMobile","useMediaQuery","isWideDesktop","useEffect","document","body","querySelector","overflow","el","current","ro","ResizeObserver","entry","contentRect","width","observe","disconnect","closeOtherSidebar","useCallback","opening","showSidenav","focus","prev","applyLeftNavWidth","newWidth","MIN_SIDENAV_WIDTH","e","preventDefault","AbortController","endResize","cursor","userSelect","handleMouseMove","clientX","handleMouseUp","setInert","removeAttribute","setAttribute","signal","addEventListener","abort","leftCol","rightCol","ariaRange","layoutContextValue","mainArea","rightSidebar","Compounds.MainArea","Compounds.RightSidebar","mainAreaChildren","header","Compounds.Header","Compounds.Body","bodyChildren","leftSidebar","main","Compounds.LeftSidebar","Compounds.Main","hasRightSidebar","mainPanelClasses","gridTemplateColumns","HEADER_NAV_HEIGHT","Fragment","next","FullLayout","assign","featureFlags","layoutProps","FeatureFlagProvider","flags","FullLayoutHeader","onOpenLeft","onOpenRight","onClick","fill","stroke","viewBox","strokeLinecap","strokeLinejoin","strokeWidth","d"],"mappings":"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"}
1
+ {"version":3,"file":"header-pane.1-3lMndU.js","sources":["../../../src/layouts/full-layout/context.tsx","../../../src/layouts/full-layout/components/main-area.tsx","../../../src/layouts/full-layout/components/body.tsx","../../../src/layouts/full-layout/components/header.tsx","../../../src/layouts/full-layout/left-sidebar-pane.tsx","../../../src/layouts/full-layout/components/left-sidebar.tsx","../../../src/layouts/full-layout/components/main.tsx","../../../src/layouts/full-layout/right-sidebar-pane.tsx","../../../src/layouts/full-layout/components/right-sidebar.tsx","../../../src/layouts/full-layout/blurry-blob.tsx","../../../src/layouts/full-layout/layout.tsx","../../../src/layouts/full-layout/header-pane.tsx"],"sourcesContent":["import React from 'react';\n\n/** Nav state derived from route (e.g. active ids). Provided by Platform; when null, layout uses props only. */\nexport interface FullLayoutNavState {\n appNavActiveId?: string;\n sectionNavActiveId?: string;\n activeArticleId?: string;\n}\n\nconst FullLayoutNavStateContext = React.createContext<FullLayoutNavState | null>(null);\n\nexport { FullLayoutNavStateContext };\n\nexport interface FullLayoutContextValue {\n isSideNavOpen: boolean;\n isRightSidebarOpen: boolean;\n toggleSidebar: () => void;\n openRightSidebar: () => void;\n closeRightSidebar: () => void;\n toggleRightSidebar: () => void;\n showSidenav: () => void;\n disableLeftSideNav: boolean;\n leftNavWidth: number;\n isMobile: boolean;\n sideNavRef: React.RefObject<HTMLDivElement | null>;\n rightSidebarRef: React.RefObject<HTMLElement | null>;\n sidebarToggleRef: React.RefObject<HTMLButtonElement | null>;\n handleResizeStart: (e: React.MouseEvent) => void;\n handleResizeKeyDown: (e: React.KeyboardEvent) => void;\n ariaValuenow: number;\n ariaValuemin: number;\n ariaValuemax: number;\n /** Mirrors `FullLayout` prop; `FullLayout.Main` uses it for viewport height when Radix ScrollArea is off. */\n disableMainScrollArea: boolean;\n}\n\nconst FullLayoutContext = React.createContext<FullLayoutContextValue | null>(null);\n\nexport interface FullLayoutProviderProps {\n value: FullLayoutContextValue;\n children: React.ReactNode;\n}\n\nexport function FullLayoutProvider({ value, children }: FullLayoutProviderProps) {\n return <FullLayoutContext.Provider value={value}>{children}</FullLayoutContext.Provider>;\n}\n\nexport function useFullLayoutContext(): FullLayoutContextValue | null {\n return React.useContext(FullLayoutContext);\n}\n\nexport interface UseRightSidebarReturn {\n /** Whether the right sidebar is currently open. */\n isOpen: boolean;\n /** Open the right sidebar (no-op if already open). */\n open: () => void;\n /** Close the right sidebar (no-op if already closed). */\n close: () => void;\n /** Toggle the right sidebar open/closed. */\n toggle: () => void;\n}\n\n/**\n * Convenience hook for programmatically controlling the right sidebar.\n *\n * Must be used inside a `<FullLayout>` tree.\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const rightSidebar = useRightSidebar();\n * return <button onClick={rightSidebar.open}>Open sidebar</button>;\n * }\n * ```\n */\nexport function useRightSidebar(): UseRightSidebarReturn {\n const ctx = React.useContext(FullLayoutContext);\n if (!ctx) {\n throw new Error('useRightSidebar must be used within a <FullLayout> component.');\n }\n\n return {\n isOpen: ctx.isRightSidebarOpen,\n open: ctx.openRightSidebar,\n close: ctx.closeRightSidebar,\n toggle: ctx.toggleRightSidebar,\n };\n}\n","import React from 'react';\n\nexport function MainArea({ children }: { children?: React.ReactNode }) {\n return <>{children}</>;\n}\nMainArea.displayName = 'FullLayout.MainArea';\n","import React from 'react';\n\nexport function Body({ children }: { children?: React.ReactNode }) {\n return <>{children}</>;\n}\nBody.displayName = 'FullLayout.Body';\n","import React, { ComponentProps } from 'react';\n\nimport { HeaderNav } from '../../header-nav';\nimport { useFullLayoutContext } from '../context';\n\nexport function Header(props: ComponentProps<typeof HeaderNav>) {\n const { onBrainfishNativeClick, ...rest } = props;\n const ctx = useFullLayoutContext();\n if (!ctx) return null;\n\n const handleNativeClick = () => {\n ctx.toggleRightSidebar();\n onBrainfishNativeClick?.();\n };\n\n return (\n <HeaderNav\n {...rest}\n showSidebarToggle={!ctx.disableLeftSideNav}\n isSideNavOpen={ctx.isSideNavOpen}\n onSideNavigationToggle={ctx.toggleSidebar}\n onBrainfishNativeClick={handleNativeClick}\n sidebarToggleRef={ctx.sidebarToggleRef as React.Ref<HTMLButtonElement>}\n />\n );\n}\nHeader.displayName = 'FullLayout.Header';\n","import React, { ComponentProps } from 'react';\n\nimport { Sidebar } from '../sidebar';\n\nimport { cn } from '@/lib/utils';\n\nexport interface FullLayoutLeftSidebarProps extends Omit<React.ComponentPropsWithoutRef<'div'>, 'children'> {\n open: boolean;\n widthPx: number;\n onResizeStart: (e: React.MouseEvent) => void;\n onResizeKeyDown: (e: React.KeyboardEvent) => void;\n ariaValuenow: number;\n ariaValuemin: number;\n ariaValuemax: number;\n sidebarProps: ComponentProps<typeof Sidebar>;\n}\n\nconst FullLayoutLeftSidebar = React.forwardRef<HTMLDivElement, FullLayoutLeftSidebarProps>(\n (\n {\n open,\n widthPx,\n onResizeStart,\n onResizeKeyDown,\n ariaValuenow,\n ariaValuemin,\n ariaValuemax,\n sidebarProps,\n className,\n ...props\n },\n ref,\n ) => {\n return (\n <div\n ref={ref}\n id=\"left-sidebar-pane\"\n data-slot=\"full-layout-left-sidebar\"\n tabIndex={-1}\n data-state={open ? 'open' : 'closed'}\n className={cn(\n 'min-w-0 overflow-hidden flex flex-col relative transition-[width] data-[state=closed]:w-0 data-[state=closed]:pointer-events-none data-[state=open]:w-full md:data-[state=open]:w-[var(--left-nav-width)]',\n className,\n )}\n style={{\n ['--left-nav-width' as string]: `${widthPx}px`,\n }}\n {...props}\n >\n <Sidebar\n {...sidebarProps}\n collapsed={!open}\n className=\"transition-[width] w-[var(--left-nav-width)] h-[calc(100dvh-var(--header-nav-height,0))]\"\n />\n\n {/* Window Splitter per APG: https://www.w3.org/ARIA/apg/patterns/windowsplitter/ */}\n {/* eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions -- focusable separator per APG Window Splitter pattern */}\n <div\n role=\"separator\"\n aria-orientation=\"vertical\"\n aria-valuenow={ariaValuenow}\n aria-valuemin={ariaValuemin}\n aria-valuemax={ariaValuemax}\n aria-label=\"Resize left sidebar\"\n aria-controls=\"left-sidebar-pane\"\n data-slot=\"full-layout-left-sidebar-resize-handle\"\n /* eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex -- focusable separator per APG Window Splitter pattern */\n tabIndex={0}\n onMouseDown={onResizeStart}\n onKeyDown={onResizeKeyDown}\n className=\"hidden lg:block absolute top-0 right-0 bottom-0 w-1 bg-transparent hover:bg-blue-500 cursor-ew-resize shrink-0 [&>div]:pointer-events-none\"\n >\n <div className=\"absolute inset-y-0 -right-1 w-3\" />\n </div>\n </div>\n );\n },\n);\n\nFullLayoutLeftSidebar.displayName = 'FullLayoutLeftSidebar';\n\nexport { FullLayoutLeftSidebar };\n","import React, { ComponentProps, useContext } from 'react';\n\nimport { Sidebar } from '../../sidebar';\nimport { FullLayoutNavStateContext, useFullLayoutContext } from '../context';\nimport { FullLayoutLeftSidebar } from '../left-sidebar-pane';\n\nexport function LeftSidebar(props: ComponentProps<typeof Sidebar>) {\n const ctx = useFullLayoutContext();\n const navState = useContext(FullLayoutNavStateContext);\n if (!ctx) return null;\n if (ctx.disableLeftSideNav) return null;\n\n const sidebarProps: ComponentProps<typeof Sidebar> =\n navState != null\n ? {\n ...props,\n appNavActiveId: navState.appNavActiveId ?? props.appNavActiveId,\n sectionNavActiveId: navState.sectionNavActiveId ?? props.sectionNavActiveId,\n activeArticleId: navState.activeArticleId ?? props.activeArticleId,\n }\n : props;\n\n return (\n <FullLayoutLeftSidebar\n ref={ctx.sideNavRef as React.Ref<HTMLDivElement>}\n open={ctx.isSideNavOpen}\n widthPx={ctx.leftNavWidth}\n onResizeStart={ctx.handleResizeStart}\n onResizeKeyDown={ctx.handleResizeKeyDown}\n ariaValuenow={ctx.ariaValuenow}\n ariaValuemin={ctx.ariaValuemin}\n ariaValuemax={ctx.ariaValuemax}\n sidebarProps={sidebarProps}\n />\n );\n}\nLeftSidebar.displayName = 'FullLayout.LeftSidebar';\n","import React from 'react';\n\nimport { useFullLayoutContext } from '../context';\n\nimport { Item } from '@/components/ui/item';\nimport { cn } from '@/lib/utils';\n\nexport function Main({ children, className }: { children?: React.ReactNode; className?: string }) {\n const ctx = useFullLayoutContext();\n const mainIsScrollContainer = ctx?.disableMainScrollArea ?? false;\n\n return (\n <Item\n className={cn(\n 'p-0',\n mainIsScrollContainer &&\n 'h-[calc(100dvh-var(--header-nav-height))] md:h-[calc(100dvh-var(--header-nav-height)-1rem)] min-h-0 overflow-y-auto p-4 md:p-8',\n className,\n )}\n >\n {children}\n </Item>\n );\n}\nMain.displayName = 'FullLayout.Main';\n","import React from 'react';\n\nimport { cn } from '@/lib/utils';\nimport { ScrollArea } from '@/components/ui/scroll-area';\n\nexport interface FullLayoutRightSidebarProps extends Omit<React.ComponentPropsWithoutRef<'aside'>, 'children'> {\n open: boolean;\n children: React.ReactNode;\n scrollable?: boolean;\n}\n\nconst FullLayoutRightSidebar = React.forwardRef<HTMLElement, FullLayoutRightSidebarProps>(\n ({ open, scrollable = true, className, children, ...props }, ref) => {\n return (\n <aside\n ref={ref as React.Ref<HTMLDivElement>}\n data-slot=\"full-layout-right-sidebar\"\n data-state={open ? 'open' : 'closed'}\n className={cn(\n 'bg-background shadow-lg flex flex-col',\n 'fixed h-[calc(100dvh-var(--header-nav-height))] z-10 w-screen transition-transform duration-300 ease-in-out data-[state=closed]:translate-x-full data-[state=open]:translate-x-0',\n 'md:relative md:h-dvh md:w-96 md:top-0',\n className,\n )}\n {...props}\n >\n <div className=\"flex flex-col flex-1 min-h-0 overflow-hidden\" data-slot=\"full-layout-right-sidebar-content\">\n {scrollable ? (\n <ScrollArea className=\"h-[calc(100dvh-var(--header-nav-height))] md:h-dvh\">{children}</ScrollArea>\n ) : (\n children\n )}\n </div>\n </aside>\n );\n },\n);\n\nFullLayoutRightSidebar.displayName = 'FullLayoutRightSidebar';\n\nexport { FullLayoutRightSidebar };\n","import React from 'react';\n\nimport { useFullLayoutContext } from '../context';\nimport { FullLayoutRightSidebar } from '../right-sidebar-pane';\n\nexport function RightSidebar({ children, scrollable }: { children?: React.ReactNode; scrollable?: boolean }) {\n const ctx = useFullLayoutContext();\n if (!ctx) return null;\n\n return (\n <FullLayoutRightSidebar\n ref={ctx.rightSidebarRef as React.Ref<HTMLElement>}\n open={ctx.isRightSidebarOpen}\n scrollable={scrollable}\n className=\"top-[var(--header-nav-height)]\"\n >\n {children}\n </FullLayoutRightSidebar>\n );\n}\nRightSidebar.displayName = 'FullLayout.RightSidebar';\n","import React from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\n\nimport { cn } from '@/lib/utils';\n\nconst blurryBlob = cva('blurry-blob', {\n variants: {\n variant: {\n topLeft: '',\n bottomRight: '!top-auto !left-auto !-bottom-[10%] !right-0 rotate-180',\n },\n },\n defaultVariants: {\n variant: 'topLeft',\n },\n});\n\ninterface BlurryBlobProps extends VariantProps<typeof blurryBlob> {\n className?: string;\n}\n\nexport const GooFilter = () => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"fixed top-0 left-0 w-0 h-0\">\n <defs>\n <filter id=\"goo\">\n <feGaussianBlur in=\"SourceGraphic\" stdDeviation=\"10\" result=\"blur\" />\n <feColorMatrix in=\"blur\" mode=\"matrix\" values=\"1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 18 -8\" result=\"goo\" />\n <feBlend in=\"SourceGraphic\" in2=\"goo\" />\n </filter>\n </defs>\n </svg>\n);\n\nconst BlurryBlob = ({ className, variant }: BlurryBlobProps) => {\n return (\n <div className={cn(blurryBlob({ variant }), className)}>\n <div className=\"gradients-container\">\n <div className=\"g1\" />\n <div className=\"g2\" />\n <div className=\"g3\" />\n <div className=\"g4\" />\n </div>\n </div>\n );\n};\n\nexport default BlurryBlob;\n","import React, { useState, useRef, useEffect, useCallback, isValidElement, useMemo } from 'react';\nimport { useMediaQuery } from 'usehooks-ts';\n\nimport { FullLayoutProvider } from './context';\nimport { HEADER_NAV_HEIGHT } from '../header-nav';\nimport * as Compounds from './components';\nimport BlurryBlob, { GooFilter } from './blurry-blob';\n\nimport { ScrollArea } from '@/components/ui/scroll-area';\nimport { FeatureFlagProvider } from '@/lib/feature-flags';\nimport type { FeatureFlags } from '@/lib/feature-flags';\nimport { cn } from '@/lib/utils';\n\nconst MIN_SIDENAV_WIDTH = 260;\nconst CLOSE_SIDENAV_THRESHOLD = MIN_SIDENAV_WIDTH - 32;\nconst MAX_SIDENAV_WIDTH = 600;\nconst RIGHT_SIDEBAR_WIDTH = 384;\n\nexport interface FullLayoutRootProps {\n children?: React.ReactNode;\n disableLeftSideNav?: boolean;\n /** When true, main column uses a plain div (no Radix ScrollArea); viewport height is applied on `FullLayout.Main`. */\n disableMainScrollArea?: boolean;\n className?: string;\n /** When true, the right sidebar is always open and cannot be toggled. */\n forceRightSidebarOpen?: boolean;\n}\n\n// Helper function to extract slots from children\nfunction extractSlots<T extends Record<string, React.ComponentType<any>>>(\n children: React.ReactNode,\n refs: T,\n): { [K in keyof T]: React.ReactElement | null } {\n const out = {} as { [K in keyof T]: React.ReactElement | null };\n const arr = React.Children.toArray(children);\n for (const key of Object.keys(refs) as (keyof T)[]) {\n const match = arr.find((c): c is React.ReactElement => isValidElement(c) && c.type === refs[key]);\n out[key] = match ?? null;\n }\n\n return out;\n}\n\n// --- Root component ---\n\nfunction FullLayoutRoot({\n children,\n disableLeftSideNav = false,\n disableMainScrollArea = false,\n className,\n forceRightSidebarOpen = false,\n}: FullLayoutRootProps) {\n // Match isMobile breakpoint (max-width: 767px) so no flash on 768–1023px\n const [isSideNavOpen, setIsSideNavOpen] = useState(() => typeof window !== 'undefined' && window.innerWidth > 767);\n const [isRightSidebarOpen, setIsRightSidebarOpen] = useState(forceRightSidebarOpen);\n const [isResizing, setIsResizing] = useState(false);\n const [gridWidth, setGridWidth] = useState(() => (typeof window !== 'undefined' ? window.innerWidth : 0));\n\n const newMinNavWidth = useMemo(\n () =>\n gridWidth > 0\n ? Math.max(MIN_SIDENAV_WIDTH, Math.min(MAX_SIDENAV_WIDTH, Math.round(gridWidth * 0.18)))\n : MIN_SIDENAV_WIDTH,\n [gridWidth],\n );\n const [leftNavWidth, setLeftNavWidth] = useState(newMinNavWidth);\n\n const sideNavRef = useRef<HTMLDivElement>(null);\n const rightSidebarRef = useRef<HTMLElement>(null);\n const sidebarToggleRef = useRef<HTMLButtonElement>(null);\n const gridRef = useRef<HTMLDivElement>(null);\n const prevSideNavOpenRef = useRef(isSideNavOpen);\n const resizeAcRef = useRef<AbortController | null>(null);\n const isMobile = useMediaQuery('(max-width: 767px)');\n const isWideDesktop = useMediaQuery('(min-width: 1280px)');\n\n // Prevent native scrollbar from appearing\n useEffect(() => {\n if (!document.body.querySelector('.sbdocs')) {\n document.body.style.overflow = 'hidden';\n }\n\n return () => {\n document.body.style.overflow = '';\n };\n }, []);\n\n // Handle grid width changes\n useEffect(() => {\n const el = gridRef.current;\n if (!el) return;\n\n const ro = new ResizeObserver(([entry]) => {\n setGridWidth(entry.contentRect.width);\n });\n ro.observe(el);\n\n return () => ro.disconnect();\n }, []);\n\n // Close other sidebar if opening a new one on wide desktop\n const closeOtherSidebar = useCallback(\n (opening: 'left' | 'right') => {\n if (isWideDesktop) return;\n if (opening === 'left') setIsRightSidebarOpen(false);\n else setIsSideNavOpen(false);\n },\n [isWideDesktop],\n );\n\n // Show left sidebar\n const showSidenav = useCallback(() => {\n closeOtherSidebar('left');\n setIsSideNavOpen(true);\n setLeftNavWidth(newMinNavWidth);\n sideNavRef.current?.focus();\n }, [closeOtherSidebar, newMinNavWidth]);\n\n // Toggle left sidebar\n const toggleSidebar = useCallback(() => {\n closeOtherSidebar('left');\n setIsSideNavOpen((prev) => !prev);\n }, [closeOtherSidebar]);\n\n // Open right sidebar (no-op if already open)\n const openRightSidebar = useCallback(() => {\n closeOtherSidebar('right');\n setIsRightSidebarOpen(true);\n }, [closeOtherSidebar]);\n\n // Close right sidebar (no-op if already closed)\n const closeRightSidebar = useCallback(() => {\n setIsRightSidebarOpen(false);\n }, []);\n\n // Toggle right sidebar\n const toggleRightSidebar = useCallback(() => {\n if (forceRightSidebarOpen) return;\n closeOtherSidebar('right');\n setIsRightSidebarOpen((prev) => !prev);\n }, [closeOtherSidebar, forceRightSidebarOpen]);\n\n // Apply left nav width - used for resizing left sidebar\n const applyLeftNavWidth = useCallback(\n (newWidth: number): boolean => {\n if (newWidth < CLOSE_SIDENAV_THRESHOLD) {\n setLeftNavWidth(newMinNavWidth);\n setIsSideNavOpen(false);\n\n return true;\n } else {\n // clamp to MAX_SIDENAV_WIDTH\n setLeftNavWidth(Math.min(MAX_SIDENAV_WIDTH, newWidth));\n\n return false;\n }\n },\n [newMinNavWidth],\n );\n\n // Handle resize start\n const handleResizeStart = useCallback((e: React.MouseEvent) => {\n e.preventDefault();\n resizeAcRef.current = new AbortController();\n setIsResizing(true);\n }, []);\n\n // Handle resize end\n const endResize = useCallback(() => {\n setIsResizing(false);\n document.body.style.cursor = '';\n document.body.style.userSelect = '';\n }, []);\n\n // Handle mouse move during resize\n const handleMouseMove = useCallback(\n (e: MouseEvent) => {\n if (!isResizing) return;\n if (applyLeftNavWidth(e.clientX)) {\n endResize();\n }\n },\n [isResizing, applyLeftNavWidth, endResize],\n );\n\n // Handle mouse up during resize\n const handleMouseUp = useCallback(() => endResize(), [endResize]);\n\n // Set inert attribute on side nav and right sidebar - disables tabbing to elements inside when sidebar is closed\n const setInert = useCallback((el: HTMLElement | null, open: boolean) => {\n if (!el) return;\n if (open) el.removeAttribute('inert');\n else el.setAttribute('inert', '');\n }, []);\n\n useEffect(() => {\n setInert(sideNavRef.current, isSideNavOpen);\n setInert(rightSidebarRef.current, isRightSidebarOpen);\n }, [isSideNavOpen, isRightSidebarOpen]);\n\n // Attach resize listeners when isResizing becomes true (controller already set in handleResizeStart)\n useEffect(() => {\n if (!isResizing || !resizeAcRef.current) return;\n\n const { signal } = resizeAcRef.current;\n document.body.style.cursor = 'ew-resize';\n document.body.style.userSelect = 'none';\n document.addEventListener('mousemove', handleMouseMove, { signal });\n document.addEventListener('mouseup', handleMouseUp, { signal });\n window.addEventListener('mouseup', handleMouseUp, { signal });\n setInert(sideNavRef.current, false);\n\n return () => {\n resizeAcRef.current?.abort();\n resizeAcRef.current = null;\n document.body.style.cursor = '';\n document.body.style.userSelect = '';\n setInert(sideNavRef.current, true);\n };\n }, [isResizing]);\n\n // Handle resize key down\n const handleResizeKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n const step = 16;\n if (e.key === 'ArrowLeft') {\n e.preventDefault();\n applyLeftNavWidth(leftNavWidth - step);\n } else if (e.key === 'ArrowRight') {\n e.preventDefault();\n applyLeftNavWidth(Math.min(MAX_SIDENAV_WIDTH, leftNavWidth + step));\n }\n },\n [leftNavWidth, applyLeftNavWidth],\n );\n\n const leftCol = disableLeftSideNav ? 0 : isSideNavOpen ? (isMobile ? gridWidth : leftNavWidth) : 0;\n const rightCol = isMobile ? 0 : isRightSidebarOpen ? RIGHT_SIDEBAR_WIDTH : 0;\n\n // Set left sidebar open state based on mobile\n useEffect(() => {\n setIsSideNavOpen(isMobile ? false : true);\n }, [isMobile]);\n\n // Focus sidebar toggle when left sidebar is closed\n useEffect(() => {\n if (prevSideNavOpenRef.current && !isSideNavOpen) {\n sidebarToggleRef.current?.focus();\n }\n prevSideNavOpenRef.current = isSideNavOpen;\n }, [isSideNavOpen]);\n\n const ariaRange = MAX_SIDENAV_WIDTH - newMinNavWidth;\n const ariaValuenow = ariaRange === 0 ? 100 : Math.round(((leftNavWidth - newMinNavWidth) / ariaRange) * 100);\n\n const layoutContextValue = useMemo(\n () => ({\n isSideNavOpen,\n isRightSidebarOpen,\n toggleSidebar,\n openRightSidebar,\n closeRightSidebar,\n toggleRightSidebar,\n showSidenav,\n disableLeftSideNav: disableLeftSideNav ?? false,\n leftNavWidth,\n isMobile,\n sideNavRef,\n rightSidebarRef,\n sidebarToggleRef,\n handleResizeStart,\n handleResizeKeyDown,\n ariaValuenow,\n ariaValuemin: 0,\n ariaValuemax: 100,\n disableMainScrollArea,\n }),\n [\n isSideNavOpen,\n isRightSidebarOpen,\n toggleSidebar,\n openRightSidebar,\n closeRightSidebar,\n toggleRightSidebar,\n showSidenav,\n leftNavWidth,\n isMobile,\n disableLeftSideNav,\n disableMainScrollArea,\n handleResizeStart,\n handleResizeKeyDown,\n ariaValuenow,\n ],\n );\n\n // --- Extract slots from children ---\n const { MainArea: mainArea, RightSidebar: rightSidebar } = extractSlots(children, {\n MainArea: Compounds.MainArea,\n RightSidebar: Compounds.RightSidebar,\n });\n const mainAreaChildren = isValidElement(mainArea)\n ? (mainArea.props as { children?: React.ReactNode }).children\n : null;\n const { Header: header, Body: body } = extractSlots(mainAreaChildren ?? null, {\n Header: Compounds.Header,\n Body: Compounds.Body,\n });\n const bodyChildren = isValidElement(body) ? (body.props as { children?: React.ReactNode }).children : null;\n const { LeftSidebar: leftSidebar, Main: main } = extractSlots(bodyChildren ?? null, {\n LeftSidebar: Compounds.LeftSidebar,\n Main: Compounds.Main,\n });\n\n const hasRightSidebar = rightSidebar != null;\n const mainPanelClasses =\n 'md:shadow-[2px_4px_12px_0_rgba(0,0,0,0.14)] md:dark:shadow-[2px_4px_12px_0_rgba(255,255,255,0.14)] md:rounded-lg';\n\n // --- Render the layout ---\n return (\n <FullLayoutProvider value={layoutContextValue}>\n <GooFilter />\n <BlurryBlob variant=\"topLeft\" />\n <BlurryBlob variant=\"bottomRight\" />\n <div\n className={cn(\n 'min-h-screen w-screen bg-background grid transition-[grid-template-columns] duration-300 ease-in-out',\n className,\n )}\n style={{\n gridTemplateColumns: hasRightSidebar ? 'minmax(0, 1fr) var(--right-col)' : 'minmax(0, 1fr)',\n ['--right-col' as string]: hasRightSidebar ? `${rightCol}px` : '0px',\n ['--header-nav-height' as string]: `${HEADER_NAV_HEIGHT}px`,\n }}\n >\n <div className=\"min-w-0 grid grid-rows-[auto_1fr]\">\n {header}\n\n <div\n ref={gridRef}\n data-sidenav-state={isSideNavOpen ? 'open' : 'closed'}\n data-right-sidebar-state={isRightSidebarOpen ? 'open' : 'closed'}\n className={cn(\n 'group/sidenav group/rightsidebar min-h-0 min-w-0 grid transition-[grid-template-columns] ease-linear',\n )}\n style={{\n gridTemplateColumns: `var(--left-col) minmax(0, 1fr)`,\n ['--left-col' as string]: `${leftCol}px`,\n }}\n >\n {disableLeftSideNav ? <div className=\"w-0\" /> : leftSidebar}\n <div className={cn('relative md:mr-4', { 'md:mx-4': !isSideNavOpen || disableLeftSideNav })}>\n {disableMainScrollArea ? (\n <div className={cn('bg-surface', mainPanelClasses)}>\n <main className=\"min-w-0 relative\">{main}</main>\n </div>\n ) : (\n <>\n <ScrollArea\n className={cn(\n 'bg-surface h-[calc(100dvh-var(--header-nav-height))] md:h-[calc(100dvh-var(--header-nav-height)-1rem)]',\n mainPanelClasses,\n )}\n >\n <div className=\"min-h-full\">\n <main className={cn('min-w-0 overflow-visible relative p-4 md:p-8')}>{main}</main>\n </div>\n </ScrollArea>\n <div\n aria-hidden\n className=\"main-scroll-fade pointer-events-none sticky bottom-4 left-0 right-0 h-16 bg-gradient-to-t from-surface to-transparent md:rounded-b-lg\"\n />\n </>\n )}\n </div>\n </div>\n </div>\n\n {hasRightSidebar ? rightSidebar : null}\n </div>\n </FullLayoutProvider>\n );\n}\n\n/**\n * Custom memo comparator: re-render only when these props change by reference/value.\n * Use this so changing other props (e.g. from a parent) does not force the layout shell to re-render.\n */\nfunction fullLayoutRootPropsAreEqual(prev: FullLayoutRootProps, next: FullLayoutRootProps): boolean {\n return (\n prev.children === next.children &&\n prev.className === next.className &&\n prev.disableLeftSideNav === next.disableLeftSideNav &&\n prev.disableMainScrollArea === next.disableMainScrollArea\n );\n}\n\nconst FullLayoutRootMemo = React.memo(FullLayoutRoot, fullLayoutRootPropsAreEqual);\n\nexport interface FullLayoutProps extends FullLayoutRootProps {\n /** Feature flags for layout/header (e.g. platform.brainfish-native.enabled). Passed through to FeatureFlagProvider. */\n featureFlags?: FeatureFlags;\n}\n\nfunction FullLayoutWithFlags(props: FullLayoutProps) {\n const { featureFlags, ...layoutProps } = props;\n\n return (\n <FeatureFlagProvider flags={featureFlags}>\n <FullLayoutRootMemo {...layoutProps} />\n </FeatureFlagProvider>\n );\n}\n\ntype FullLayoutCompound = typeof FullLayoutWithFlags & {\n MainArea: typeof Compounds.MainArea;\n Body: typeof Compounds.Body;\n Header: typeof Compounds.Header;\n LeftSidebar: typeof Compounds.LeftSidebar;\n Main: typeof Compounds.Main;\n RightSidebar: typeof Compounds.RightSidebar;\n};\n\nconst FullLayout: FullLayoutCompound = Object.assign(FullLayoutWithFlags, {\n MainArea: Compounds.MainArea,\n Body: Compounds.Body,\n Header: Compounds.Header,\n LeftSidebar: Compounds.LeftSidebar,\n Main: Compounds.Main,\n RightSidebar: Compounds.RightSidebar,\n});\n\nexport default FullLayout;\n","import React from 'react';\n\nimport { cn } from '@/lib/utils';\n\nexport interface FullLayoutHeaderProps extends React.ComponentPropsWithoutRef<'header'> {\n onOpenLeft?: () => void;\n onOpenRight?: () => void;\n}\n\nconst FullLayoutHeader = React.forwardRef<HTMLElement, FullLayoutHeaderProps>(\n ({ onOpenLeft, onOpenRight, className, children, ...props }, ref) => {\n return (\n <header\n ref={ref as React.Ref<HTMLHeadingElement>}\n data-slot=\"full-layout-header\"\n className={cn('h-16 bg-white shadow-md flex items-center px-4 shrink-0 sticky top-0 z-20', className)}\n {...props}\n >\n {onOpenLeft != null && (\n <button\n data-slot=\"full-layout-header-trigger-left\"\n type=\"button\"\n onClick={onOpenLeft}\n className=\"p-2 hover:bg-gray-100 rounded-lg transition-colors mr-4 lg:hidden\"\n aria-label=\"Toggle menu\"\n >\n <svg className=\"size-6\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M4 6h16M4 12h16M4 18h16\" />\n </svg>\n </button>\n )}\n <div data-slot=\"full-layout-header-center\" className=\"flex-1 min-w-0\">\n {children}\n </div>\n {onOpenRight != null && (\n <div data-slot=\"full-layout-header-trigger-right\" className=\"ml-auto\">\n <button\n type=\"button\"\n onClick={onOpenRight}\n className=\"p-2 hover:bg-gray-100 rounded-lg transition-colors\"\n aria-label=\"Toggle chat\"\n >\n <svg className=\"size-6\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M8 10h.01M12 10h.01M16 10h.01M9 16H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-5l-5 5v-5z\"\n />\n </svg>\n </button>\n </div>\n )}\n </header>\n );\n },\n);\n\nFullLayoutHeader.displayName = 'FullLayoutHeader';\n\nexport { FullLayoutHeader };\n"],"names":["FullLayoutNavStateContext","React","createContext","FullLayoutContext","FullLayoutProvider","value","children","createElement","Provider","useFullLayoutContext","useContext","useRightSidebar","ctx","Error","isOpen","isRightSidebarOpen","open","openRightSidebar","close","closeRightSidebar","toggle","toggleRightSidebar","MainArea","Body","Header","props","onBrainfishNativeClick","rest","HeaderNav","showSidebarToggle","disableLeftSideNav","isSideNavOpen","onSideNavigationToggle","toggleSidebar","sidebarToggleRef","displayName","FullLayoutLeftSidebar","forwardRef","widthPx","onResizeStart","onResizeKeyDown","ariaValuenow","ariaValuemin","ariaValuemax","sidebarProps","className","ref","id","tabIndex","cn","style","Sidebar","collapsed","role","onMouseDown","onKeyDown","LeftSidebar","navState","appNavActiveId","sectionNavActiveId","activeArticleId","sideNavRef","leftNavWidth","handleResizeStart","handleResizeKeyDown","Main","mainIsScrollContainer","disableMainScrollArea","Item","FullLayoutRightSidebar","scrollable","ScrollArea","RightSidebar","rightSidebarRef","blurryBlob","cva","variants","variant","topLeft","bottomRight","defaultVariants","GooFilter","xmlns","in","stdDeviation","result","mode","values","in2","BlurryBlob","MAX_SIDENAV_WIDTH","extractSlots","refs","out","arr","Children","toArray","key","Object","keys","match","find","c","isValidElement","type","FullLayoutRootMemo","memo","forceRightSidebarOpen","setIsSideNavOpen","useState","window","innerWidth","setIsRightSidebarOpen","isResizing","setIsResizing","gridWidth","setGridWidth","newMinNavWidth","useMemo","Math","max","min","round","setLeftNavWidth","useRef","gridRef","prevSideNavOpenRef","resizeAcRef","isMobile","useMediaQuery","isWideDesktop","useEffect","document","body","querySelector","overflow","el","current","ro","ResizeObserver","entry","contentRect","width","observe","disconnect","closeOtherSidebar","useCallback","opening","showSidenav","focus","prev","applyLeftNavWidth","newWidth","MIN_SIDENAV_WIDTH","e","preventDefault","AbortController","endResize","cursor","userSelect","handleMouseMove","clientX","handleMouseUp","setInert","removeAttribute","setAttribute","signal","addEventListener","abort","leftCol","rightCol","ariaRange","layoutContextValue","mainArea","rightSidebar","Compounds.MainArea","Compounds.RightSidebar","mainAreaChildren","header","Compounds.Header","Compounds.Body","bodyChildren","leftSidebar","main","Compounds.LeftSidebar","Compounds.Main","hasRightSidebar","mainPanelClasses","gridTemplateColumns","HEADER_NAV_HEIGHT","Fragment","next","FullLayout","assign","featureFlags","layoutProps","FeatureFlagProvider","flags","FullLayoutHeader","onOpenLeft","onOpenRight","onClick","fill","stroke","viewBox","strokeLinecap","strokeLinejoin","strokeWidth","d"],"mappings":"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"}
@@ -1,25 +1,25 @@
1
- import*as e from"react";import{ScrollArea as t}from"../components/ui/scroll-area.js";import{c as a}from"./utils.C6Qu-kwd.js";import{ArrowBendUpLeft as r,X as n,MagnifyingGlass as i,Folder as l,FolderOpen as s,FolderDashed as o,DotsThree as c,Plus as d,FileDashed as m,File as u,Lightning as p,Article as f}from"@phosphor-icons/react";import{B as h}from"./button.D_2SonNs.js";import{useToggle as g,useDebounceValue as v}from"usehooks-ts";import{Input as b}from"../components/ui/input.js";import{TreeStateContext as y,Button as E,useTreeData as x,useDragAndDrop as A,DropIndicator as k,Tree as S,TreeItem as N,TreeItemContent as I,Collection as w}from"react-aria-components";import{ButtonGroup as C}from"../components/ui/button-group.js";import{Spinner as M}from"../components/ui/spinner.js";import{u as z}from"./hooks.BQTKhHSv.js";const L=e.createContext(null);function j({collapsed:t,ItemLinkComponent:a,activeArticleId:r,onSelectArticle:n,onExpandArticle:i,onSearchArticles:l,onAddArticle:s,onMoreActions:o,canMoveArticle:c,onMoveArticle:d,children:m}){const[u,p]=e.useState(!1),[f,h]=e.useState(""),[g,v]=e.useState(null),b=e.useCallback(e=>{const t=e.trim();p(""!==t),l?.(e)},[l]),y=e.useMemo(()=>({collapsed:t,ItemLinkComponent:a,activeArticleId:r,onSearchArticles:l,onSelectArticle:n,onExpandArticle:i,onAddArticle:s,onMoreActions:o,canMoveArticle:c,onMoveArticle:d,isSearching:u,searchValue:f,setSearchValue:h,lastSelectedArticleId:g,setLastSelectedArticleId:v,handleSearchArticles:b}),[u,f,g,t,a,r,n,i,l,s,o,c,d,b]);/* @__PURE__ */
1
+ import*as e from"react";import{ScrollArea as t}from"../components/ui/scroll-area.js";import{c as a}from"./utils.C6Qu-kwd.js";import{ArrowBendUpLeft as r,X as n,MagnifyingGlass as i,Folder as l,FolderOpen as s,FolderDashed as o,DotsThree as c,Plus as d,FileDashed as m,File as u,Lightning as p,Article as f}from"@phosphor-icons/react";import{B as h}from"./button.D_2SonNs.js";import{useToggle as g,useDebounceValue as v}from"usehooks-ts";import{Input as b}from"../components/ui/input.js";import{TreeStateContext as y,Button as x,useTreeData as E,useDragAndDrop as A,DropIndicator as k,Tree as S,TreeItem as N,TreeItemContent as I,Collection as w}from"react-aria-components";import{ButtonGroup as C}from"../components/ui/button-group.js";import{Spinner as M}from"../components/ui/spinner.js";import{u as z}from"./hooks.BQTKhHSv.js";const L=e.createContext(null);function j({collapsed:t,ItemLinkComponent:a,activeArticleId:r,onSelectArticle:n,onExpandArticle:i,onSearchArticles:l,onAddArticle:s,onMoreActions:o,canMoveArticle:c,onMoveArticle:d,children:m}){const[u,p]=e.useState(!1),[f,h]=e.useState(""),[g,v]=e.useState(null),b=e.useCallback(e=>{const t=e.trim();p(""!==t),l?.(e)},[l]),y=e.useMemo(()=>({collapsed:t,ItemLinkComponent:a,activeArticleId:r,onSearchArticles:l,onSelectArticle:n,onExpandArticle:i,onAddArticle:s,onMoreActions:o,canMoveArticle:c,onMoveArticle:d,isSearching:u,searchValue:f,setSearchValue:h,lastSelectedArticleId:g,setLastSelectedArticleId:v,handleSearchArticles:b}),[u,f,g,t,a,r,n,i,l,s,o,c,d,b]);/* @__PURE__ */
2
2
  return e.createElement(L.Provider,{value:y},m)}function B(){const t=e.useContext(L);if(!t)throw new Error("useSidebar must be used within SidebarProvider");return t}function P({className:t,items:r,activeId:n}){const{ItemLinkComponent:i}=B();/* @__PURE__ */
3
3
  return e.createElement("nav",{className:a("flex flex-col",t),"aria-label":"App section navigation"},r.map(t=>/* @__PURE__ */e.createElement(i,{key:t.id,href:t.href,"data-sidebar-item-id":t.id,"data-sidebar-item-type":"section","data-sidebar-section-nav-item-selected":t.id===n,className:a("flex p-2 mx-4 text-sm text-default relative rounded-lg","after:transition-opacity after:absolute after:top-0 after:bottom-0 after:-right-4 after:w-2 after:bg-primary after:rounded-l-md after:opacity-0","hover:bg-dark-200 focus:bg-dark-200 hover:text-accent-foreground focus:text-accent-foreground",t.id===n&&"font-bold after:opacity-100")},t.label)))}function $({className:n,items:i,activeId:l,showBack:s,onBack:o,sectionNavItems:c,sectionNavActiveId:d}){const{collapsed:m,ItemLinkComponent:u}=B(),p=!!s&&!!o;/* @__PURE__ */
4
4
  return e.createElement("nav",{className:a("flex flex-col gap-2",n),"aria-label":"App navigation"},p&&/* @__PURE__ */e.createElement(h,{variant:"link",className:a("py-2 text-base text-default w-full mx-4",m?"justify-center":"justify-start"),size:"icon",onClick:o},
5
5
  /* @__PURE__ */e.createElement(r,{"aria-hidden":"true"}),
6
- /* @__PURE__ */e.createElement("span",{className:a(m&&"sr-only")},"back to Brainfish")),/* @__PURE__ */e.createElement(t,{className:"min-h-0 max-h-[calc(100dvh-var(--header-nav-height)-5rem)]"},/* @__PURE__ */e.createElement("div",{className:"flex flex-col gap-2 mx-4"},i?.map(t=>/* @__PURE__ */e.createElement(e.Fragment,{key:t.id},/* @__PURE__ */e.createElement(u,{className:a("flex p-2 rounded-lg gap-1 text-base text-default items-center hover:text-primary-foreground focus:text-primary-foreground",t.id===l?"bg-primary text-primary-foreground font-bold":"hover:bg-dark-200 focus:bg-dark-200"),href:t.href,"data-sidebar-item-id":t.id,"data-sidebar-item-type":"app","data-sidebar-app-nav-item-selected":t.id===l},t.Icon?/* @__PURE__ */e.createElement(t.Icon,{weight:t.id===l?"fill":"regular",size:16}):null,
6
+ /* @__PURE__ */e.createElement("span",{className:a(m&&"sr-only")},"back to Brainfish")),/* @__PURE__ */e.createElement(t,{className:"min-h-0 max-h-[calc(100dvh-var(--header-nav-height)-5rem)]"},/* @__PURE__ */e.createElement("div",{className:"flex flex-col gap-2 mx-4"},i?.map(t=>/* @__PURE__ */e.createElement(e.Fragment,{key:t.id},/* @__PURE__ */e.createElement(u,{className:a("flex p-2 rounded-lg gap-1 text-base text-default items-center",t.id===l?"bg-primary text-primary-foreground font-bold hover:text-primary-foreground focus:text-primary-foreground":"hover:bg-dark-200 focus:bg-dark-200 hover:text-accent-foreground focus:text-accent-foreground"),href:t.href,"data-sidebar-item-id":t.id,"data-sidebar-item-type":"app","data-sidebar-app-nav-item-selected":t.id===l},t.Icon?/* @__PURE__ */e.createElement(t.Icon,{weight:t.id===l?"fill":"regular",size:16}):null,
7
7
  /* @__PURE__ */e.createElement("span",{className:a("transition-opacity duration-200",m&&"opacity-0 sr-only")},t.label)),t.id===l&&c&&c.length>0&&!m&&/* @__PURE__ */e.createElement(P,{className:a("flex-shrink-0"),items:c,activeId:d}))))))}function K(){const{handleSearchArticles:t,searchValue:a,setSearchValue:r}=B(),[l,,s]=g(!1),o=e.useRef(null);return e.useEffect(()=>{l&&t?.(a)},[a,t,l]),/* @__PURE__ */e.createElement("div",{className:"mb-2"},/* @__PURE__ */e.createElement(b,{ref:o,className:"h-auto text-subtlest border-border-subtle",startIcon:i,endIcon:a?n:void 0,onEndIconClick:()=>{r(""),t?.("")},value:a,onChange:e=>{const a=e.target.value;l||s(!0),r(a),""===a.trim()&&(t(""),s(!1))},placeholder:"Find an article","aria-label":"Find an article",type:"search"}))}function V({children:t}){/* @__PURE__ */
8
- return e.createElement(E,{slot:"chevron",className:"relative z-30 flex p-0"},/* @__PURE__ */e.createElement("span",{className:"relative inline-flex size-3 items-center justify-center"},t))}function D({item:t,hasChildItems:r,isSelected:n,isExpanded:i,ItemLinkComponent:f,onAddArticle:g,isAddingArticle:v,isLoadingChildren:b,onMoreActions:x,level:A}){const{isSearching:k}=B(),S=e.useContext(y),N=Boolean(n),I=!!(g&&!v||x),w="draft"===t.value.status;let z;switch(t.value.status){case"draft":z="(draft)";break;case"unpublished":z="(unpublished changes)";break;default:z=""}const L=/* @__PURE__ */e.createElement(V,null,/* @__PURE__ */e.createElement(l,{"aria-hidden":"true",weight:"fill",className:a("absolute size-3 transition-opacity duration-200 ease-out",i?"opacity-0":"opacity-100")}),/* @__PURE__ */e.createElement(s,{"aria-hidden":"true",weight:"fill",className:a("absolute size-3 transition-opacity duration-200 ease-out",i?"opacity-100":"opacity-0")})),j=/* @__PURE__ */e.createElement(V,null,/* @__PURE__ */e.createElement(o,{"aria-hidden":"true",weight:"fill",className:a("absolute size-3 transition-opacity duration-200 ease-out",i?"opacity-0":"opacity-100")}),/* @__PURE__ */e.createElement(s,{"aria-hidden":"true",weight:"fill",className:a("absolute size-3 transition-opacity duration-200 ease-out",i?"opacity-100":"opacity-0")})),P=/* @__PURE__ */e.createElement(e.Fragment,null,/* @__PURE__ */e.createElement("span",{className:"sr-only"},"Knowledge Discovery"),/* @__PURE__ */e.createElement(p,{"aria-hidden":"true",weight:"fill",className:"size-3 shrink-0 text-blue-600"})),$=r?/* @__PURE__ */e.createElement(V,null,/* @__PURE__ */e.createElement("span",{className:"text-blue-600"},P)):/* @__PURE__ */e.createElement("span",{className:"flex size-3 shrink-0 items-center justify-center text-blue-600"},P),K=/* @__PURE__ */e.createElement("span",{className:"flex size-3 shrink-0 items-center justify-center"},/* @__PURE__ */e.createElement(u,{"aria-hidden":"true",className:"size-3"})),D=/* @__PURE__ */e.createElement("span",{className:"flex size-3 shrink-0 items-center justify-center"},/* @__PURE__ */e.createElement("span",{className:"sr-only"},"Unpublished Changes"),/* @__PURE__ */e.createElement(m,{"aria-hidden":"true",className:"size-3"})),F=/* @__PURE__ */e.createElement("span",{className:"flex size-3 shrink-0 items-center justify-center",role:"status","aria-label":`Loading nested articles for ${t.value.label}`},
8
+ return e.createElement(x,{slot:"chevron",className:"relative z-30 flex p-0"},/* @__PURE__ */e.createElement("span",{className:"relative inline-flex size-3 items-center justify-center"},t))}function D({item:t,hasChildItems:r,isSelected:n,isExpanded:i,ItemLinkComponent:f,onAddArticle:g,isAddingArticle:v,isLoadingChildren:b,onMoreActions:E,level:A}){const{isSearching:k}=B(),S=e.useContext(y),N=Boolean(n),I=!!(g&&!v||E),w="draft"===t.value.status;let z;switch(t.value.status){case"draft":z="(draft)";break;case"unpublished":z="(unpublished changes)";break;default:z=""}const L=/* @__PURE__ */e.createElement(V,null,/* @__PURE__ */e.createElement(l,{"aria-hidden":"true",weight:"fill",className:a("absolute size-3 transition-opacity duration-200 ease-out",i?"opacity-0":"opacity-100")}),/* @__PURE__ */e.createElement(s,{"aria-hidden":"true",weight:"fill",className:a("absolute size-3 transition-opacity duration-200 ease-out",i?"opacity-100":"opacity-0")})),j=/* @__PURE__ */e.createElement(V,null,/* @__PURE__ */e.createElement(o,{"aria-hidden":"true",weight:"fill",className:a("absolute size-3 transition-opacity duration-200 ease-out",i?"opacity-0":"opacity-100")}),/* @__PURE__ */e.createElement(s,{"aria-hidden":"true",weight:"fill",className:a("absolute size-3 transition-opacity duration-200 ease-out",i?"opacity-100":"opacity-0")})),P=/* @__PURE__ */e.createElement(e.Fragment,null,/* @__PURE__ */e.createElement("span",{className:"sr-only"},"Knowledge Discovery"),/* @__PURE__ */e.createElement(p,{"aria-hidden":"true",weight:"fill",className:"size-3 shrink-0 text-blue-600"})),$=r?/* @__PURE__ */e.createElement(V,null,/* @__PURE__ */e.createElement("span",{className:"text-blue-600"},P)):/* @__PURE__ */e.createElement("span",{className:"flex size-3 shrink-0 items-center justify-center text-blue-600"},P),K=/* @__PURE__ */e.createElement("span",{className:"flex size-3 shrink-0 items-center justify-center"},/* @__PURE__ */e.createElement(u,{"aria-hidden":"true",className:"size-3"})),D=/* @__PURE__ */e.createElement("span",{className:"flex size-3 shrink-0 items-center justify-center"},/* @__PURE__ */e.createElement("span",{className:"sr-only"},"Unpublished Changes"),/* @__PURE__ */e.createElement(m,{"aria-hidden":"true",className:"size-3"})),F=/* @__PURE__ */e.createElement("span",{className:"flex size-3 shrink-0 items-center justify-center",role:"status","aria-label":`Loading nested articles for ${t.value.label}`},
9
9
  /* @__PURE__ */e.createElement(M,{"aria-hidden":"true",className:"size-3 text-current"}),
10
10
  /* @__PURE__ */e.createElement("span",{className:"sr-only"},"Loading nested articles for ",t.value.label));/* @__PURE__ */
11
11
  return e.createElement("div",{style:{"--line-offset":"0.875rem"},"aria-busy":b||void 0,className:a("group relative flex items-center gap-1 rounded-md py-1 pl-1 ml-[calc((var(--tree-item-level)-1)*var(--line-offset))] pr-4 h-9",w&&"text-subtlest italic",n?"bg-lime-100 text-primary-foreground font-bold after:absolute after:-right-0.5 after:top-1/2 after:h-1/2 after:w-1 after:-translate-y-1/2 after:bg-lime-400":"hover:bg-dark-200 hover:text-accent-foreground")},Array.from({length:A-1},(a,r)=>/* @__PURE__ */e.createElement("span",{key:`${t.value.label}-${r+1}`,style:{"--item-line-level":r+1},className:"absolute w-[1px] bg-dark-400 -top-2 h-9 left-[calc(-4px-var(--line-offset)*(var(--item-line-level)-1))]","aria-hidden":!0})),
12
- /* @__PURE__ */e.createElement(E,{slot:"drag",className:"sr-only"},"Drag ",t.value.label),k?null:b?F:((e,t)=>{if("discovery"===e)return $;const a="unpublished"===e||"draft"===e;return t?a?j:L:a?D:K})(t.value.status,r),
13
- /* @__PURE__ */e.createElement(f,{href:t.value.href,title:`${t.value.label} ${z}`,"data-sidebar-item-id":t.value.id,"data-sidebar-item-type":"article",className:a("min-w-0 text-inherit text-sm truncate flex-1 after:absolute after:inset-0 after:z-10 pr-1",n&&"text-primary-foreground"),onClick:e=>{N&&(e.preventDefault(),e.stopPropagation()),r&&S&&S.toggleKey(t.key)}},t.value.label),I&&/* @__PURE__ */e.createElement(C,{orientation:"horizontal",className:a("absolute h-4 my-auto right-0.5 top-0 bottom-0 z-20 hidden items-center rounded-xl","group-hover:flex group-focus-within:flex",n?"bg-lime-100 text-primary-foreground":"bg-dark-200")},x&&/* @__PURE__ */e.createElement(h,{variant:"ghost",size:"icon","aria-label":`More actions for ${t.value.label}`,className:"size-4 [&_svg]:size-3.5",onClick:e=>{e.stopPropagation(),x?.(t.value.id)}},
12
+ /* @__PURE__ */e.createElement(x,{slot:"drag",className:"sr-only"},"Drag ",t.value.label),k?null:b?F:((e,t)=>{if("discovery"===e)return $;const a="unpublished"===e||"draft"===e;return t?a?j:L:a?D:K})(t.value.status,r),
13
+ /* @__PURE__ */e.createElement(f,{href:t.value.href,title:`${t.value.label} ${z}`,"data-sidebar-item-id":t.value.id,"data-sidebar-item-type":"article",className:a("min-w-0 text-inherit text-sm truncate flex-1 after:absolute after:inset-0 after:z-10 pr-1",n&&"text-primary-foreground"),onClick:e=>{N&&(e.preventDefault(),e.stopPropagation()),r&&S&&S.toggleKey(t.key)}},t.value.label),I&&/* @__PURE__ */e.createElement(C,{orientation:"horizontal",className:a("absolute h-4 my-auto right-0.5 top-0 bottom-0 z-20 hidden items-center rounded-xl","group-hover:flex group-focus-within:flex",n?"bg-lime-100 text-primary-foreground":"bg-dark-200")},E&&/* @__PURE__ */e.createElement(h,{variant:"ghost",size:"icon","aria-label":`More actions for ${t.value.label}`,className:"size-4 [&_svg]:size-3.5",onClick:e=>{e.stopPropagation(),E?.(t.value.id)}},
14
14
  /* @__PURE__ */e.createElement(c,{"aria-hidden":"true",weight:"bold"})),g&&!v&&/* @__PURE__ */e.createElement(h,{variant:"ghost",size:"icon","aria-label":`Add article to ${t.value.label}`,className:"size-4 [&_svg]:size-3.5",onClick:e=>{e.stopPropagation(),g?.(t.value.id)}},
15
- /* @__PURE__ */e.createElement(d,{"aria-hidden":"true"}))))}function F(e,t=null,a=0,r=[]){return e.forEach((e,n)=>{r.push({item:e,parentId:t,index:n,depth:a}),e.items?.length&&F(e.items,e.id,a+1,r)}),r}let _=0;function R(e,t,a=[]){for(const r of e){if(r.id===t)return a;if(r.items&&r.items.length>0){const e=R(r.items,t,[...a,r.id]);if(e)return e}}return null}function H(e){return e.map(e=>({...e.value,items:e.children?.length?H(e.children):e.value.items}))}function U({articles:t,isSearching:a,renderEmptyState:r}){const{ItemLinkComponent:n,activeArticleId:i,lastSelectedArticleId:l,setLastSelectedArticleId:s,onSelectArticle:o,onExpandArticle:c,handleSearchArticles:d,setSearchValue:m,canMoveArticle:u,onMoveArticle:p,onAddArticle:f,onMoreActions:h}=B(),g=i??l??void 0,v=x({initialItems:t,getKey:e=>e.id,getChildren:e=>e.items??[]}),b=e.useRef(t);e.useEffect(()=>{if(b.current===t)return;b.current=t;const e=function(e,t){const a=F(e),r=F(t),n=new Map(a.map(e=>[e.item.id,e])),i=new Map(r.map(e=>[e.item.id,e])),l=[];return a.filter(e=>!i.has(e.item.id)).sort((e,t)=>t.depth-e.depth).forEach(e=>{l.push({type:"remove",id:e.item.id})}),r.forEach(e=>{const t=n.get(e.item.id);var a,r;t?(t.parentId===e.parentId&&t.index===e.index||l.push({type:"move",id:e.item.id,parentId:e.parentId,index:e.index}),a=t.item,r=e.item,(a.label!==r.label||a.href!==r.href||a.status!==r.status||a.hasChildren!==r.hasChildren||a.isLoadingChildren!==r.isLoadingChildren)&&l.push({type:"update",id:e.item.id,item:e.item})):l.push({type:"insert",parentId:e.parentId,index:e.index,item:e.item})}),l}(H(v.items),t);0!==e.length&&e.forEach(e=>{switch(e.type){case"remove":v.remove(e.id);break;case"insert":v.insert(e.parentId,e.index,e.item);break;case"move":v.move(e.id,e.parentId,e.index);break;case"update":v.update(e.id,e.item)}})},[t,v]);const{dragAndDropHooks:y}=A({getItems:(e,t)=>t.map(e=>({"text/plain":e.value.label})),onMove:e=>{if(a)return;const t=Array.from(e.keys)[0];if(!t)return;const r=v.getItem(e.target.key);if(!r)return;let n,i;if("on"===e.target.dropPosition)n=e.target.key.toString(),i=r.children?.length??0;else{n=r.parentKey?.toString()??null;const t=(n?v.getItem(n)?.children??[]:v.items).findIndex(t=>t.key===e.target.key);i="before"===e.target.dropPosition?t:t+1}const l={id:t.toString(),parentId:n,index:i};if(u&&!u(l))return;const s=v.getItem(t),o=s?.parentKey?.toString()??null,c=(o?v.getItem(o)?.children??[]:v.items).findIndex(e=>e.key===t);"on"===e.target.dropPosition?v.move(t,n,i):"before"===e.target.dropPosition?v.moveBefore(e.target.key,e.keys):v.moveAfter(e.target.key,e.keys);const d=p?.(l);d&&"function"==typeof d.then&&d.catch(()=>{v.move(t,o,c)})},renderDropIndicator:t=>/* @__PURE__ */e.createElement(k,{target:t,className:"outline outline-1 outline-lime-200 ml-[calc(var(--tree-item-level)*0.5rem)]"})}),[E,C]=e.useState(/* @__PURE__ */new Set),M=e.useMemo(()=>null!=g?/* @__PURE__ */new Set([g]):E,[g,E]),z=e.useMemo(()=>{if(!g||a||!t.length)return[];return R(t,g)??[]},[t,g,a]),[L,j]=e.useState(/* @__PURE__ */new Set),P=e.useMemo(()=>/* @__PURE__ */new Set([...z,...L]),[z,L]);e.useEffect(()=>{i&&s(null)},[i,l,s]);const $=e.useRef(/* @__PURE__ */new Set),[K,V]=e.useState(/* @__PURE__ */new Set),U=e.useCallback(e=>{if(a||!f||$.current.has(e))return;$.current.add(e),V(new Set($.current));const t="__placeholder_"+ ++_,r={id:t,label:"Untitled",href:"",status:"draft"};v.append(e,r),j(t=>/* @__PURE__ */new Set([...t,e])),f(e).then(a=>{v.remove(t),v.append(e,a),C(/* @__PURE__ */new Set([a.id])),o?.(a.id),$.current.delete(e),V(new Set($.current))},()=>{v.remove(t),$.current.delete(e),V(new Set($.current))})},[a,f,v,o]),q=e.useCallback(e=>{o?.(e),null==i&&C(/* @__PURE__ */new Set([e])),a&&(s(e),m(""),d?.(""))},[i,d,a,o,s,m]);/* @__PURE__ */
15
+ /* @__PURE__ */e.createElement(d,{"aria-hidden":"true"}))))}function F(e,t=null,a=0,r=[]){return e.forEach((e,n)=>{r.push({item:e,parentId:t,index:n,depth:a}),e.items?.length&&F(e.items,e.id,a+1,r)}),r}let _=0;function R(e,t,a=[]){for(const r of e){if(r.id===t)return a;if(r.items&&r.items.length>0){const e=R(r.items,t,[...a,r.id]);if(e)return e}}return null}function H(e){return e.map(e=>({...e.value,items:e.children?.length?H(e.children):e.value.items}))}function U({articles:t,isSearching:a,renderEmptyState:r}){const{ItemLinkComponent:n,activeArticleId:i,lastSelectedArticleId:l,setLastSelectedArticleId:s,onSelectArticle:o,onExpandArticle:c,handleSearchArticles:d,setSearchValue:m,canMoveArticle:u,onMoveArticle:p,onAddArticle:f,onMoreActions:h}=B(),g=i??l??void 0,v=E({initialItems:t,getKey:e=>e.id,getChildren:e=>e.items??[]}),b=e.useRef(t);e.useEffect(()=>{if(b.current===t)return;b.current=t;const e=function(e,t){const a=F(e),r=F(t),n=new Map(a.map(e=>[e.item.id,e])),i=new Map(r.map(e=>[e.item.id,e])),l=[];return a.filter(e=>!i.has(e.item.id)).sort((e,t)=>t.depth-e.depth).forEach(e=>{l.push({type:"remove",id:e.item.id})}),r.forEach(e=>{const t=n.get(e.item.id);var a,r;t?(t.parentId===e.parentId&&t.index===e.index||l.push({type:"move",id:e.item.id,parentId:e.parentId,index:e.index}),a=t.item,r=e.item,(a.label!==r.label||a.href!==r.href||a.status!==r.status||a.hasChildren!==r.hasChildren||a.isLoadingChildren!==r.isLoadingChildren)&&l.push({type:"update",id:e.item.id,item:e.item})):l.push({type:"insert",parentId:e.parentId,index:e.index,item:e.item})}),l}(H(v.items),t);0!==e.length&&e.forEach(e=>{switch(e.type){case"remove":v.remove(e.id);break;case"insert":v.insert(e.parentId,e.index,e.item);break;case"move":v.move(e.id,e.parentId,e.index);break;case"update":v.update(e.id,e.item)}})},[t,v]);const{dragAndDropHooks:y}=A({getItems:(e,t)=>t.map(e=>({"text/plain":e.value.label})),onMove:e=>{if(a)return;const t=Array.from(e.keys)[0];if(!t)return;const r=v.getItem(e.target.key);if(!r)return;let n,i;if("on"===e.target.dropPosition)n=e.target.key.toString(),i=r.children?.length??0;else{n=r.parentKey?.toString()??null;const t=(n?v.getItem(n)?.children??[]:v.items).findIndex(t=>t.key===e.target.key);i="before"===e.target.dropPosition?t:t+1}const l={id:t.toString(),parentId:n,index:i};if(u&&!u(l))return;const s=v.getItem(t),o=s?.parentKey?.toString()??null,c=(o?v.getItem(o)?.children??[]:v.items).findIndex(e=>e.key===t);"on"===e.target.dropPosition?v.move(t,n,i):"before"===e.target.dropPosition?v.moveBefore(e.target.key,e.keys):v.moveAfter(e.target.key,e.keys);const d=p?.(l);d&&"function"==typeof d.then&&d.catch(()=>{v.move(t,o,c)})},renderDropIndicator:t=>/* @__PURE__ */e.createElement(k,{target:t,className:"outline outline-1 outline-lime-200 ml-[calc(var(--tree-item-level)*0.5rem)]"})}),[x,C]=e.useState(/* @__PURE__ */new Set),M=e.useMemo(()=>null!=g?/* @__PURE__ */new Set([g]):x,[g,x]),z=e.useMemo(()=>{if(!g||a||!t.length)return[];return R(t,g)??[]},[t,g,a]),[L,j]=e.useState(/* @__PURE__ */new Set),P=e.useMemo(()=>/* @__PURE__ */new Set([...z,...L]),[z,L]);e.useEffect(()=>{i&&s(null)},[i,l,s]);const $=e.useRef(/* @__PURE__ */new Set),[K,V]=e.useState(/* @__PURE__ */new Set),U=e.useCallback(e=>{if(a||!f||$.current.has(e))return;$.current.add(e),V(new Set($.current));const t="__placeholder_"+ ++_,r={id:t,label:"Untitled",href:"",status:"draft"};v.append(e,r),j(t=>/* @__PURE__ */new Set([...t,e])),f(e).then(a=>{v.remove(t),v.append(e,a),C(/* @__PURE__ */new Set([a.id])),o?.(a.id),$.current.delete(e),V(new Set($.current))},()=>{v.remove(t),$.current.delete(e),V(new Set($.current))})},[a,f,v,o]),q=e.useCallback(e=>{o?.(e),null==i&&C(/* @__PURE__ */new Set([e])),a&&(s(e),m(""),d?.(""))},[i,d,a,o,s,m]);/* @__PURE__ */
16
16
  return e.createElement(S,{"aria-label":a?"Search results":"Articles tree",items:v.items,renderEmptyState:r,dragAndDropHooks:a?void 0:y,className:"flex flex-col",selectionBehavior:"toggle",selectionMode:"single",expandedKeys:P,onExpandedChange:e=>{(function(e,t){const a=new Set(Array.from(e,e=>e.toString()));return Array.from(t,e=>e.toString()).filter(e=>!a.has(e))})(P,e).forEach(e=>{c?.(e)}),j(e)},selectedKeys:M,disallowEmptySelection:!0,onSelectionChange:e=>{if("all"!==e){null==g&&C(e);const t=Array.from(e)?.[0];t&&q(t.toString())}}},function t(r){/* @__PURE__ */
17
17
  return e.createElement(N,{className:"list-none",textValue:r.value.label,id:r.value.id,hasChildItems:r.value.hasChildren},
18
18
  /* @__PURE__ */e.createElement(I,null,t=>/* @__PURE__ */e.createElement(D,{ItemLinkComponent:n,item:r,onAddArticle:!a&&f?U:void 0,isAddingArticle:!a&&K.has(r.value.id),isLoadingChildren:!a&&r.value.isLoadingChildren,onMoreActions:h?e=>h(e):void 0,...t})),!a&&r.children&&/* @__PURE__ */e.createElement(w,{items:r.children},t))})}const q={leading:!0,trailing:!0};function G({articles:t,className:r,isLoadingArticles:n}){const{isSearching:i,searchValue:l,onAddArticle:s}=B(),{contains:o}=z(),c=l.trim(),[d]=v(i?c:"",i?400:0,i?q:void 0),m=!i&&(n??void 0===t),u=e.useCallback(()=>/* @__PURE__ */e.createElement("div",{className:"flex min-h-20 items-center justify-center text-muted-foreground",role:"status","aria-live":"polite","aria-label":"Loading articles list"},
19
19
  /* @__PURE__ */e.createElement(M,{className:"size-5","aria-hidden":"true"}),
20
20
  /* @__PURE__ */e.createElement("span",{className:"sr-only"},"Loading articles list")),[]),p=!(m||i||t&&0!==t.length),g=e.useMemo(()=>{if(i){if(""===c||""===d)return[];const e=[],a=d,r=t=>{for(const n of t)o(n.label,a)&&e.push({...n,hasChildren:!1,items:[]}),n.items?.length&&r(n.items)};return r(t??[]),e}return t&&t.length>0?t:[]},[t,i,c,d,o]);/* @__PURE__ */
21
- return e.createElement("div",{className:a("flex flex-col gap-0.5 px-4",r)},p&&/* @__PURE__ */e.createElement(h,{variant:"ghost",className:"text-subtlest",onClick:()=>s?.(null).catch(()=>{})},/* @__PURE__ */e.createElement(f,{"aria-hidden":"true"}),"Create first article or folder"),m?/* @__PURE__ */e.createElement(U,{isSearching:i,articles:[],renderEmptyState:u}):/* @__PURE__ */e.createElement(e.Fragment,null,/* @__PURE__ */e.createElement(K,null),/* @__PURE__ */e.createElement("nav",{"aria-label":"Articles navigation"},/* @__PURE__ */e.createElement(U,{key:i?""===c?"search:empty":`search:${d}`:"browse",isSearching:i,articles:g??[]}))))}const J=e.forwardRef(function({className:r,ItemLinkComponent:n,collapsed:i,showAppBack:l,onAppBack:s,appNavItems:o,appNavActiveId:c,isLoadingArticles:d,sectionNavItems:m,sectionNavActiveId:u,activeArticleId:p,showArticles:f,articles:h,onSelectArticle:g,onExpandArticle:v,onSearchArticles:b,onAddArticle:y,onMoreActions:E,canMoveArticle:x,onMoveArticle:A,...k},S){/* @__PURE__ */
22
- return e.createElement(j,{collapsed:!!i,ItemLinkComponent:n,activeArticleId:p,onSelectArticle:g,onExpandArticle:v,onSearchArticles:b,onAddArticle:y,onMoreActions:E,canMoveArticle:x,onMoveArticle:A},
21
+ return e.createElement("div",{className:a("flex flex-col gap-0.5 px-4",r)},p&&/* @__PURE__ */e.createElement(h,{variant:"ghost",className:"text-subtlest",onClick:()=>s?.(null).catch(()=>{})},/* @__PURE__ */e.createElement(f,{"aria-hidden":"true"}),"Create first article or folder"),m?/* @__PURE__ */e.createElement(U,{isSearching:i,articles:[],renderEmptyState:u}):/* @__PURE__ */e.createElement(e.Fragment,null,/* @__PURE__ */e.createElement(K,null),/* @__PURE__ */e.createElement("nav",{"aria-label":"Articles navigation"},/* @__PURE__ */e.createElement(U,{key:i?""===c?"search:empty":`search:${d}`:"browse",isSearching:i,articles:g??[]}))))}const J=e.forwardRef(function({className:r,ItemLinkComponent:n,collapsed:i,showAppBack:l,onAppBack:s,appNavItems:o,appNavActiveId:c,isLoadingArticles:d,sectionNavItems:m,sectionNavActiveId:u,activeArticleId:p,showArticles:f,articles:h,onSelectArticle:g,onExpandArticle:v,onSearchArticles:b,onAddArticle:y,onMoreActions:x,canMoveArticle:E,onMoveArticle:A,...k},S){/* @__PURE__ */
22
+ return e.createElement(j,{collapsed:!!i,ItemLinkComponent:n,activeArticleId:p,onSelectArticle:g,onExpandArticle:v,onSearchArticles:b,onAddArticle:y,onMoreActions:x,canMoveArticle:E,onMoveArticle:A},
23
23
  /* @__PURE__ */e.createElement("aside",{ref:S,...k,className:a("py-4 transition-width duration-200 ease-in-out flex flex-col h-dvh",i?"w-[64px]":"w-[260px]",r),"aria-label":"Application navigation"},
24
24
  /* @__PURE__ */e.createElement($,{className:a("flex-shrink-0",o&&o.length>0&&"pb-4",!i&&"border-b border-border-subtle"),showBack:l,items:o,activeId:c,onBack:s,sectionNavItems:m,sectionNavActiveId:u}),!i&&/* @__PURE__ */e.createElement(e.Fragment,null,f&&/* @__PURE__ */e.createElement(t,null,/* @__PURE__ */e.createElement(G,{className:"py-4 max-w-[var(--left-nav-width,inherit)]",articles:h,isLoadingArticles:d})))))});export{J as S,B as u};
25
- //# sourceMappingURL=sidebar.BdJe6AhO.js.map
25
+ //# sourceMappingURL=sidebar.HOrQaimG.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sidebar.HOrQaimG.js","sources":["../../../src/layouts/sidebar/context.tsx","../../../src/layouts/sidebar/section-nav/section-nav.tsx","../../../src/layouts/sidebar/app-nav/app-nav.tsx","../../../src/layouts/sidebar/article-nav/article-search.tsx","../../../src/layouts/sidebar/article-nav/article-item.tsx","../../../src/layouts/sidebar/article-nav/tree-sync.ts","../../../src/layouts/sidebar/article-nav/article-tree.tsx","../../../src/layouts/sidebar/article-nav/expansion.ts","../../../src/layouts/sidebar/article-nav/article-nav.tsx","../../../src/layouts/sidebar/sidebar.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { ArticleNavItem, ItemLinkComponent } from './types';\n\nexport interface SidebarContextProps {\n collapsed: boolean;\n ItemLinkComponent: ItemLinkComponent;\n activeArticleId?: string;\n onSelectArticle?: (id: string) => void;\n onExpandArticle?: (id: string) => void;\n onSearchArticles?: (value: string) => void;\n onAddArticle?: (parentId: string | null) => Promise<ArticleNavItem>;\n onMoreActions?: (articleId: string) => void;\n canMoveArticle?: (move: { id: string; parentId: string | null; index: number }) => boolean;\n onMoveArticle?: (moved: { id: string; parentId: string | null; index: number }) => void | Promise<void>;\n}\n\nexport interface SidebarContextValue extends SidebarContextProps {\n handleSearchArticles: (value: string) => void;\n isSearching: boolean;\n searchValue: string;\n setSearchValue: React.Dispatch<React.SetStateAction<string>>;\n /** Set when user selects from search results; tree uses this until activeArticleId catches up */\n lastSelectedArticleId: string | null;\n setLastSelectedArticleId: React.Dispatch<React.SetStateAction<string | null>>;\n}\n\nconst SidebarContext = React.createContext<SidebarContextValue | null>(null);\n\nexport function SidebarProvider({\n collapsed,\n ItemLinkComponent,\n activeArticleId,\n onSelectArticle,\n onExpandArticle,\n onSearchArticles,\n onAddArticle,\n onMoreActions,\n canMoveArticle,\n onMoveArticle,\n children,\n}: React.PropsWithChildren<SidebarContextProps>) {\n const [isSearching, setIsSearching] = React.useState<boolean>(false);\n const [searchValue, setSearchValue] = React.useState<string>('');\n const [lastSelectedArticleId, setLastSelectedArticleId] = React.useState<string | null>(null);\n\n const handleSearchArticles = React.useCallback(\n (value: string) => {\n const trimmedValue = value.trim();\n setIsSearching(trimmedValue !== '');\n onSearchArticles?.(value);\n },\n [onSearchArticles],\n );\n\n const contextValue = React.useMemo<SidebarContextValue>(\n () => ({\n collapsed,\n ItemLinkComponent,\n activeArticleId,\n onSearchArticles,\n onSelectArticle,\n onExpandArticle,\n onAddArticle,\n onMoreActions,\n canMoveArticle,\n onMoveArticle,\n isSearching,\n searchValue,\n setSearchValue,\n lastSelectedArticleId,\n setLastSelectedArticleId,\n handleSearchArticles,\n }),\n [\n isSearching,\n searchValue,\n lastSelectedArticleId,\n collapsed,\n ItemLinkComponent,\n activeArticleId,\n onSelectArticle,\n onExpandArticle,\n onSearchArticles,\n onAddArticle,\n onMoreActions,\n canMoveArticle,\n onMoveArticle,\n handleSearchArticles,\n ],\n );\n\n return <SidebarContext.Provider value={contextValue}>{children}</SidebarContext.Provider>;\n}\n\nexport function useSidebar() {\n const sidebarContext = React.useContext(SidebarContext);\n\n if (!sidebarContext) throw new Error('useSidebar must be used within SidebarProvider');\n\n return sidebarContext;\n}\n","import * as React from 'react';\n\nimport { SidebarNavItem } from '../types';\nimport { useSidebar } from '../context';\n\nimport { cn } from '@/lib/utils';\n\nexport interface SectionNavProps {\n className?: string;\n items: SidebarNavItem[];\n activeId?: string;\n}\n\nexport function SectionNav({ className, items, activeId }: SectionNavProps) {\n const { ItemLinkComponent } = useSidebar();\n\n return (\n <nav className={cn('flex flex-col', className)} aria-label=\"App section navigation\">\n {items.map((item) => (\n <ItemLinkComponent\n key={item.id}\n href={item.href}\n data-sidebar-item-id={item.id}\n data-sidebar-item-type=\"section\"\n data-sidebar-section-nav-item-selected={item.id === activeId}\n className={cn(\n 'flex p-2 mx-4 text-sm text-default relative rounded-lg',\n 'after:transition-opacity after:absolute after:top-0 after:bottom-0 after:-right-4 after:w-2 after:bg-primary after:rounded-l-md after:opacity-0',\n 'hover:bg-dark-200 focus:bg-dark-200 hover:text-accent-foreground focus:text-accent-foreground',\n item.id === activeId && 'font-bold after:opacity-100',\n )}\n >\n {item.label}\n </ItemLinkComponent>\n ))}\n </nav>\n );\n}\n","import * as React from 'react';\nimport { ArrowBendUpLeft } from '@phosphor-icons/react';\n\nimport type { SidebarNavItem } from '../types';\nimport { useSidebar } from '../context';\nimport { SectionNav } from '../section-nav';\n\nimport { Button } from '@/components/ui/button';\nimport { ScrollArea } from '@/components/ui/scroll-area';\nimport { cn } from '@/lib/utils';\n\nexport interface AppNavProps {\n className?: string;\n items?: SidebarNavItem[];\n activeId?: string;\n showBack?: boolean;\n onBack?: () => void;\n sectionNavItems?: SidebarNavItem[];\n sectionNavActiveId?: string;\n}\n\nexport function AppNav({\n className,\n items,\n activeId,\n showBack,\n onBack,\n sectionNavItems,\n sectionNavActiveId,\n}: AppNavProps) {\n const { collapsed, ItemLinkComponent } = useSidebar();\n\n const hasBack = !!showBack && !!onBack;\n\n return (\n <nav className={cn('flex flex-col gap-2', className)} aria-label=\"App navigation\">\n {hasBack && (\n <Button\n variant=\"link\"\n className={cn('py-2 text-base text-default w-full mx-4', collapsed ? 'justify-center' : 'justify-start')}\n size=\"icon\"\n onClick={onBack}\n >\n <ArrowBendUpLeft aria-hidden=\"true\" />\n <span className={cn(collapsed && 'sr-only')}>back to Brainfish</span>\n </Button>\n )}\n <ScrollArea className=\"min-h-0 max-h-[calc(100dvh-var(--header-nav-height)-5rem)]\">\n <div className=\"flex flex-col gap-2 mx-4\">\n {items?.map((item) => (\n <React.Fragment key={item.id}>\n <ItemLinkComponent\n className={cn(\n 'flex p-2 rounded-lg gap-1 text-base text-default items-center',\n item.id === activeId\n ? 'bg-primary text-primary-foreground font-bold hover:text-primary-foreground focus:text-primary-foreground'\n : 'hover:bg-dark-200 focus:bg-dark-200 hover:text-accent-foreground focus:text-accent-foreground',\n )}\n href={item.href}\n data-sidebar-item-id={item.id}\n data-sidebar-item-type=\"app\"\n data-sidebar-app-nav-item-selected={item.id === activeId}\n >\n {item.Icon ? <item.Icon weight={item.id === activeId ? 'fill' : 'regular'} size={16} /> : null}\n <span className={cn('transition-opacity duration-200', collapsed && 'opacity-0 sr-only')}>\n {item.label}\n </span>\n </ItemLinkComponent>\n {item.id === activeId && sectionNavItems && sectionNavItems.length > 0 && !collapsed && (\n <SectionNav className={cn('flex-shrink-0')} items={sectionNavItems} activeId={sectionNavActiveId} />\n )}\n </React.Fragment>\n ))}\n </div>\n </ScrollArea>\n </nav>\n );\n}\n","import * as React from 'react';\nimport { MagnifyingGlass, X } from '@phosphor-icons/react';\nimport { useToggle } from 'usehooks-ts';\n\nimport { useSidebar } from '../context';\n\nimport { Input } from '@/components/ui/input';\n\nexport function ArticleSearch() {\n const { handleSearchArticles, searchValue, setSearchValue } = useSidebar();\n const [searchInteracted, , setSearchInteracted] = useToggle(false);\n const searchInputRef = React.useRef<HTMLInputElement>(null);\n\n React.useEffect(() => {\n if (searchInteracted) handleSearchArticles?.(searchValue);\n }, [searchValue, handleSearchArticles, searchInteracted]);\n\n return (\n <div className=\"mb-2\">\n <Input\n ref={searchInputRef}\n className=\"h-auto text-subtlest border-border-subtle\"\n startIcon={MagnifyingGlass}\n endIcon={searchValue ? X : undefined}\n onEndIconClick={() => {\n setSearchValue('');\n handleSearchArticles?.('');\n }}\n value={searchValue}\n onChange={(e) => {\n const value = e.target.value;\n if (!searchInteracted) {\n setSearchInteracted(true);\n }\n setSearchValue(value);\n if (value.trim() === '') {\n handleSearchArticles('');\n setSearchInteracted(false);\n }\n }}\n placeholder=\"Find an article\"\n aria-label=\"Find an article\"\n type=\"search\"\n />\n </div>\n );\n}\n","import * as React from 'react';\nimport { Folder, FolderDashed, FolderOpen, File, FileDashed, DotsThree, Lightning, Plus } from '@phosphor-icons/react';\nimport { Key, TreeItemContentRenderProps, TreeStateContext, Button as AriaButton } from 'react-aria-components';\n\nimport { ArticleNavItem, ItemLinkComponent } from '../types';\nimport { useSidebar } from '../context';\n\nimport { cn } from '@/lib/utils';\nimport { Button } from '@/components/ui/button';\nimport { ButtonGroup } from '@/components/ui/button-group';\nimport { Spinner } from '@/components/ui/spinner';\n\ntype ArticleItemTreeNode = {\n key: Key;\n value: ArticleNavItem;\n children: ArticleItemTreeNode[] | null;\n};\n\nfunction FolderSlotButton({ children }: { children: React.ReactNode }) {\n return (\n <AriaButton slot=\"chevron\" className=\"relative z-30 flex p-0\">\n <span className=\"relative inline-flex size-3 items-center justify-center\">{children}</span>\n </AriaButton>\n );\n}\n\nexport interface ArticleItemProps extends TreeItemContentRenderProps {\n ItemLinkComponent: ItemLinkComponent;\n item: ArticleItemTreeNode;\n onAddArticle?: (parentId: string) => void;\n isAddingArticle?: boolean;\n isLoadingChildren?: boolean;\n onMoreActions?: (articleId: string) => void;\n}\n\nexport function ArticleItem({\n item,\n hasChildItems,\n isSelected,\n isExpanded,\n ItemLinkComponent,\n onAddArticle,\n isAddingArticle,\n isLoadingChildren,\n onMoreActions,\n level,\n}: ArticleItemProps) {\n const { isSearching } = useSidebar();\n const treeState = React.useContext(TreeStateContext);\n const shouldPreventNavigation = Boolean(isSelected);\n\n const handleAddClick = (e: React.MouseEvent) => {\n e.stopPropagation();\n onAddArticle?.(item.value.id);\n };\n\n const handleMoreClick = (e: React.MouseEvent) => {\n e.stopPropagation();\n onMoreActions?.(item.value.id);\n };\n\n const handleItemClick = (e: React.MouseEvent) => {\n if (shouldPreventNavigation) {\n e.preventDefault();\n e.stopPropagation();\n }\n\n if (hasChildItems && treeState) {\n treeState.toggleKey(item.key);\n }\n };\n\n const showActions = !!((onAddArticle && !isAddingArticle) || onMoreActions);\n\n const isDraft = item.value.status === 'draft';\n\n let statusLabel: string;\n switch (item.value.status) {\n case 'draft':\n statusLabel = '(draft)';\n break;\n case 'unpublished':\n statusLabel = '(unpublished changes)';\n break;\n default:\n statusLabel = '';\n }\n\n const folderIcon = (\n <FolderSlotButton>\n <Folder\n aria-hidden=\"true\"\n weight=\"fill\"\n className={cn(\n 'absolute size-3 transition-opacity duration-200 ease-out',\n isExpanded ? 'opacity-0' : 'opacity-100',\n )}\n />\n <FolderOpen\n aria-hidden=\"true\"\n weight=\"fill\"\n className={cn(\n 'absolute size-3 transition-opacity duration-200 ease-out',\n isExpanded ? 'opacity-100' : 'opacity-0',\n )}\n />\n </FolderSlotButton>\n );\n\n const folderWithChangesIcon = (\n <FolderSlotButton>\n <FolderDashed\n aria-hidden=\"true\"\n weight=\"fill\"\n className={cn(\n 'absolute size-3 transition-opacity duration-200 ease-out',\n isExpanded ? 'opacity-0' : 'opacity-100',\n )}\n />\n <FolderOpen\n aria-hidden=\"true\"\n weight=\"fill\"\n className={cn(\n 'absolute size-3 transition-opacity duration-200 ease-out',\n isExpanded ? 'opacity-100' : 'opacity-0',\n )}\n />\n </FolderSlotButton>\n );\n\n const discoveryIconContent = (\n <>\n <span className=\"sr-only\">Knowledge Discovery</span>\n <Lightning aria-hidden=\"true\" weight=\"fill\" className=\"size-3 shrink-0 text-blue-600\" />\n </>\n );\n\n const discoveryIcon = hasChildItems ? (\n <FolderSlotButton>\n <span className=\"text-blue-600\">{discoveryIconContent}</span>\n </FolderSlotButton>\n ) : (\n <span className=\"flex size-3 shrink-0 items-center justify-center text-blue-600\">{discoveryIconContent}</span>\n );\n\n const fileIcon = (\n <span className=\"flex size-3 shrink-0 items-center justify-center\">\n <File aria-hidden=\"true\" className=\"size-3\" />\n </span>\n );\n\n const fileWithChangesIcon = (\n <span className=\"flex size-3 shrink-0 items-center justify-center\">\n <span className=\"sr-only\">Unpublished Changes</span>\n <FileDashed aria-hidden=\"true\" className=\"size-3\" />\n </span>\n );\n\n const loadingFolderIcon = (\n <span\n className=\"flex size-3 shrink-0 items-center justify-center\"\n role=\"status\"\n aria-label={`Loading nested articles for ${item.value.label}`}\n >\n <Spinner aria-hidden=\"true\" className=\"size-3 text-current\" />\n <span className=\"sr-only\">Loading nested articles for {item.value.label}</span>\n </span>\n );\n\n const renderStatusIcon = (status: ArticleNavItem['status'], hasChildItems: boolean) => {\n if (status === 'discovery') {\n return discoveryIcon;\n }\n\n const hasChanges = status === 'unpublished' || status === 'draft';\n\n if (hasChildItems) {\n return hasChanges ? folderWithChangesIcon : folderIcon;\n } else {\n return hasChanges ? fileWithChangesIcon : fileIcon;\n }\n };\n\n return (\n <div\n style={{ ['--line-offset' as string]: '0.875rem' }}\n aria-busy={isLoadingChildren || undefined}\n className={cn(\n 'group relative flex items-center gap-1 rounded-md py-1 pl-1 ml-[calc((var(--tree-item-level)-1)*var(--line-offset))] pr-4 h-9',\n isDraft && 'text-subtlest italic',\n isSelected\n ? 'bg-lime-100 text-primary-foreground font-bold after:absolute after:-right-0.5 after:top-1/2 after:h-1/2 after:w-1 after:-translate-y-1/2 after:bg-lime-400'\n : 'hover:bg-dark-200 hover:text-accent-foreground',\n )}\n >\n {Array.from({ length: level - 1 }, (_, i) => (\n <span\n key={`${item.value.label}-${i + 1}`}\n style={{ ['--item-line-level' as string]: i + 1 }}\n // Don't mess with the calc: forumula for multiple lines.\n className=\"absolute w-[1px] bg-dark-400 -top-2 h-9 left-[calc(-4px-var(--line-offset)*(var(--item-line-level)-1))]\"\n aria-hidden={true}\n />\n ))}\n\n <AriaButton slot=\"drag\" className=\"sr-only\">\n Drag {item.value.label}\n </AriaButton>\n\n {isSearching ? null : isLoadingChildren ? loadingFolderIcon : renderStatusIcon(item.value.status, hasChildItems)}\n\n <ItemLinkComponent\n href={item.value.href}\n title={`${item.value.label} ${statusLabel}`}\n data-sidebar-item-id={item.value.id}\n data-sidebar-item-type=\"article\"\n className={cn(\n 'min-w-0 text-inherit text-sm truncate flex-1 after:absolute after:inset-0 after:z-10 pr-1',\n isSelected && 'text-primary-foreground',\n )}\n onClick={handleItemClick}\n >\n {item.value.label}\n </ItemLinkComponent>\n\n {showActions && (\n <ButtonGroup\n orientation=\"horizontal\"\n className={cn(\n 'absolute h-4 my-auto right-0.5 top-0 bottom-0 z-20 hidden items-center rounded-xl',\n 'group-hover:flex group-focus-within:flex',\n isSelected ? 'bg-lime-100 text-primary-foreground' : 'bg-dark-200',\n )}\n >\n {onMoreActions && (\n <Button\n variant=\"ghost\"\n size=\"icon\"\n aria-label={`More actions for ${item.value.label}`}\n className=\"size-4 [&_svg]:size-3.5\"\n onClick={handleMoreClick}\n >\n <DotsThree aria-hidden=\"true\" weight=\"bold\" />\n </Button>\n )}\n\n {onAddArticle && !isAddingArticle && (\n <Button\n variant=\"ghost\"\n size=\"icon\"\n aria-label={`Add article to ${item.value.label}`}\n className=\"size-4 [&_svg]:size-3.5\"\n onClick={handleAddClick}\n >\n <Plus aria-hidden=\"true\" />\n </Button>\n )}\n </ButtonGroup>\n )}\n </div>\n );\n}\n","import type { ArticleNavItem } from '../types';\n\ntype TreeEntry = {\n item: ArticleNavItem;\n parentId: string | null;\n index: number;\n depth: number;\n};\n\nexport type TreeSyncOperation =\n | { type: 'remove'; id: string }\n | { type: 'insert'; parentId: string | null; index: number; item: ArticleNavItem }\n | { type: 'move'; id: string; parentId: string | null; index: number }\n | { type: 'update'; id: string; item: ArticleNavItem };\n\nfunction flattenArticles(items: ArticleNavItem[], parentId: string | null = null, depth = 0, result: TreeEntry[] = []): TreeEntry[] {\n items.forEach((item, index) => {\n result.push({ item, parentId, index, depth });\n if (item.items?.length) {\n flattenArticles(item.items, item.id, depth + 1, result);\n }\n });\n\n return result;\n}\n\nfunction haveSameValue(a: ArticleNavItem, b: ArticleNavItem) {\n return (\n a.label === b.label &&\n a.href === b.href &&\n a.status === b.status &&\n a.hasChildren === b.hasChildren &&\n a.isLoadingChildren === b.isLoadingChildren\n );\n}\n\nexport function buildArticleTreeSyncOperations(currentArticles: ArticleNavItem[], nextArticles: ArticleNavItem[]): TreeSyncOperation[] {\n const currentEntries = flattenArticles(currentArticles);\n const nextEntries = flattenArticles(nextArticles);\n\n const currentMap = new Map(currentEntries.map((entry) => [entry.item.id, entry]));\n const nextMap = new Map(nextEntries.map((entry) => [entry.item.id, entry]));\n const operations: TreeSyncOperation[] = [];\n\n currentEntries\n .filter((entry) => !nextMap.has(entry.item.id))\n .sort((a, b) => b.depth - a.depth)\n .forEach((entry) => {\n operations.push({ type: 'remove', id: entry.item.id });\n });\n\n nextEntries.forEach((entry) => {\n const currentEntry = currentMap.get(entry.item.id);\n\n if (!currentEntry) {\n operations.push({\n type: 'insert',\n parentId: entry.parentId,\n index: entry.index,\n item: entry.item,\n });\n\n return;\n }\n\n if (currentEntry.parentId !== entry.parentId || currentEntry.index !== entry.index) {\n operations.push({\n type: 'move',\n id: entry.item.id,\n parentId: entry.parentId,\n index: entry.index,\n });\n }\n\n if (!haveSameValue(currentEntry.item, entry.item)) {\n operations.push({\n type: 'update',\n id: entry.item.id,\n item: entry.item,\n });\n }\n });\n\n return operations;\n}\n","import * as React from 'react';\nimport {\n useDragAndDrop,\n useTreeData,\n Tree,\n TreeItem,\n TreeItemContent,\n Collection,\n DropIndicator,\n type Key,\n} from 'react-aria-components';\n\nimport { ArticleNavItem } from '../types';\nimport { ArticleItem } from './article-item';\nimport { useSidebar } from '../context';\nimport { getNewlyExpandedKeys } from './expansion';\nimport { buildArticleTreeSyncOperations } from './tree-sync';\n\nlet placeholderCounter = 0;\n\ninterface ArticleTreeProps {\n articles: ArticleNavItem[];\n isSearching?: boolean;\n renderEmptyState?: () => React.ReactNode;\n}\n\nexport function getParentKeys(items: ArticleNavItem[], targetId: string, parents: string[] = []): string[] | null {\n for (const item of items) {\n if (item.id === targetId) {\n return parents;\n }\n if (item.items && item.items.length > 0) {\n const result = getParentKeys(item.items, targetId, [...parents, item.id]);\n if (result) return result;\n }\n }\n\n return null;\n}\n\ntype ArticleTreeNode = {\n value: ArticleNavItem;\n children: ArticleTreeNode[] | null;\n};\n\nfunction treeNodesToArticleNavItems(items: ArticleTreeNode[]): ArticleNavItem[] {\n return items.map((item) => ({\n ...item.value,\n items: item.children?.length ? treeNodesToArticleNavItems(item.children) : item.value.items,\n }));\n}\n\nexport function ArticleTree({ articles, isSearching, renderEmptyState }: ArticleTreeProps) {\n const {\n ItemLinkComponent,\n activeArticleId,\n lastSelectedArticleId,\n setLastSelectedArticleId,\n onSelectArticle,\n onExpandArticle,\n handleSearchArticles,\n setSearchValue,\n canMoveArticle,\n onMoveArticle,\n onAddArticle,\n onMoreActions,\n } = useSidebar();\n\n const effectiveActiveId = activeArticleId ?? lastSelectedArticleId ?? undefined;\n\n const articlesTree = useTreeData({\n initialItems: articles,\n getKey: (articleItem) => articleItem.id,\n getChildren: (articleItem) => articleItem.items ?? [],\n });\n\n const prevArticlesRef = React.useRef(articles);\n React.useEffect(() => {\n if (prevArticlesRef.current === articles) return;\n\n prevArticlesRef.current = articles;\n\n const currentArticles = treeNodesToArticleNavItems(articlesTree.items);\n const operations = buildArticleTreeSyncOperations(currentArticles, articles);\n\n if (operations.length === 0) return;\n\n operations.forEach((operation) => {\n switch (operation.type) {\n case 'remove':\n articlesTree.remove(operation.id);\n break;\n case 'insert':\n articlesTree.insert(operation.parentId, operation.index, operation.item);\n break;\n case 'move':\n articlesTree.move(operation.id, operation.parentId, operation.index);\n break;\n case 'update':\n articlesTree.update(operation.id, operation.item);\n break;\n }\n });\n }, [articles, articlesTree]);\n\n const { dragAndDropHooks } = useDragAndDrop({\n getItems: (_keys, items: typeof articlesTree.items) =>\n items.map((item) => ({\n 'text/plain': item.value.label,\n })),\n onMove: (e) => {\n if (isSearching) return;\n const movedArticleId = Array.from(e.keys)[0];\n if (!movedArticleId) return;\n\n const targetItem = articlesTree.getItem(e.target.key);\n if (!targetItem) return;\n\n let movedToParentId: string | null;\n let movedToIndex: number;\n\n if (e.target.dropPosition === 'on') {\n movedToParentId = e.target.key.toString();\n movedToIndex = targetItem.children?.length ?? 0;\n } else {\n movedToParentId = targetItem.parentKey?.toString() ?? null;\n const siblings = movedToParentId ? (articlesTree.getItem(movedToParentId)?.children ?? []) : articlesTree.items;\n const targetIndex = siblings.findIndex((i) => i.key === e.target.key);\n movedToIndex = e.target.dropPosition === 'before' ? targetIndex : targetIndex + 1;\n }\n\n const moveDetails = {\n id: movedArticleId.toString(),\n parentId: movedToParentId,\n index: movedToIndex,\n };\n\n if (canMoveArticle && !canMoveArticle(moveDetails)) {\n return;\n }\n\n const movedItem = articlesTree.getItem(movedArticleId);\n const originalParentId = movedItem?.parentKey?.toString() ?? null;\n const originalSiblings = originalParentId\n ? (articlesTree.getItem(originalParentId)?.children ?? [])\n : articlesTree.items;\n const originalIndex = originalSiblings.findIndex((i) => i.key === movedArticleId);\n\n if (e.target.dropPosition === 'on') {\n articlesTree.move(movedArticleId, movedToParentId, movedToIndex);\n } else if (e.target.dropPosition === 'before') {\n articlesTree.moveBefore(e.target.key, e.keys);\n } else {\n articlesTree.moveAfter(e.target.key, e.keys);\n }\n\n const result = onMoveArticle?.(moveDetails);\n\n if (result && typeof result.then === 'function') {\n result.catch(() => {\n articlesTree.move(movedArticleId, originalParentId, originalIndex);\n });\n }\n },\n renderDropIndicator: (target) => (\n <DropIndicator\n target={target}\n className=\"outline outline-1 outline-lime-200 ml-[calc(var(--tree-item-level)*0.5rem)]\"\n />\n ),\n });\n\n // Selection when there's no active article from URL/context; used so the tree can show a selection before navigation.\n const [localSelectedKeys, setLocalSelectedKeys] = React.useState<Set<Key>>(new Set());\n const selectedKeys = React.useMemo(\n () => (effectiveActiveId != null ? new Set<Key>([effectiveActiveId]) : localSelectedKeys),\n [effectiveActiveId, localSelectedKeys],\n );\n\n const pathToActive = React.useMemo(() => {\n if (!effectiveActiveId || isSearching || !articles.length) return [];\n const path = getParentKeys(articles, effectiveActiveId);\n\n return path ?? [];\n }, [articles, effectiveActiveId, isSearching]);\n\n const [expandedKeysState, setExpandedKeysState] = React.useState<Set<Key>>(new Set());\n const expandedKeys = React.useMemo(\n () => new Set<Key>([...pathToActive, ...expandedKeysState]),\n [pathToActive, expandedKeysState],\n );\n\n React.useEffect(() => {\n if (!activeArticleId) return;\n setLastSelectedArticleId(null);\n }, [activeArticleId, lastSelectedArticleId, setLastSelectedArticleId]);\n\n const pendingAddIdsRef = React.useRef<Set<string>>(new Set());\n const [pendingAddIds, setPendingAddIds] = React.useState<Set<string>>(new Set());\n\n const handleAddArticle = React.useCallback(\n (parentId: string) => {\n if (isSearching || !onAddArticle || pendingAddIdsRef.current.has(parentId)) return;\n\n pendingAddIdsRef.current.add(parentId);\n setPendingAddIds(new Set(pendingAddIdsRef.current));\n\n const tempId = `__placeholder_${++placeholderCounter}`;\n const placeholder: ArticleNavItem = { id: tempId, label: 'Untitled', href: '', status: 'draft' };\n\n articlesTree.append(parentId, placeholder);\n setExpandedKeysState((prev) => new Set([...prev, parentId]));\n\n onAddArticle(parentId).then(\n (created) => {\n articlesTree.remove(tempId);\n articlesTree.append(parentId, created);\n // Highlight the newly created article in the tree.\n setLocalSelectedKeys(new Set([created.id]));\n onSelectArticle?.(created.id);\n pendingAddIdsRef.current.delete(parentId);\n setPendingAddIds(new Set(pendingAddIdsRef.current));\n },\n () => {\n articlesTree.remove(tempId);\n pendingAddIdsRef.current.delete(parentId);\n setPendingAddIds(new Set(pendingAddIdsRef.current));\n },\n );\n },\n [isSearching, onAddArticle, articlesTree, onSelectArticle],\n );\n\n const navigateToArticleId = React.useCallback(\n (articleId: string) => {\n onSelectArticle?.(articleId);\n // No URL/store id: keep highlight in sync for Storybook and other uncontrolled hosts.\n if (activeArticleId == null) {\n setLocalSelectedKeys(new Set<Key>([articleId]));\n }\n if (isSearching) {\n setLastSelectedArticleId(articleId);\n setSearchValue('');\n handleSearchArticles?.('');\n }\n },\n [activeArticleId, handleSearchArticles, isSearching, onSelectArticle, setLastSelectedArticleId, setSearchValue],\n );\n\n return (\n <Tree\n aria-label={isSearching ? 'Search results' : 'Articles tree'}\n items={articlesTree.items}\n renderEmptyState={renderEmptyState}\n dragAndDropHooks={isSearching ? undefined : dragAndDropHooks}\n className=\"flex flex-col\"\n // toggle → selectOnFocus off in React Aria, so ArrowUp/Down only move focus; Space updates selection → onSelectionChange.\n selectionBehavior=\"toggle\"\n selectionMode=\"single\"\n expandedKeys={expandedKeys}\n onExpandedChange={(nextExpandedKeys) => {\n const newlyExpandedKeys = getNewlyExpandedKeys(expandedKeys, nextExpandedKeys);\n\n newlyExpandedKeys.forEach((key) => {\n onExpandArticle?.(key);\n });\n\n setExpandedKeysState(nextExpandedKeys);\n }}\n selectedKeys={selectedKeys}\n disallowEmptySelection\n onSelectionChange={(selection) => {\n if (selection !== 'all') {\n // Keep local selection in sync when we're not driven by URL/active article.\n if (effectiveActiveId == null) setLocalSelectedKeys(selection);\n const selected = Array.from(selection)?.[0];\n\n if (selected) {\n navigateToArticleId(selected.toString());\n }\n }\n }}\n >\n {function renderItem(item) {\n return (\n <TreeItem\n className=\"list-none\"\n textValue={item.value.label}\n id={item.value.id}\n hasChildItems={item.value.hasChildren}\n >\n <TreeItemContent>\n {(props) => (\n <ArticleItem\n ItemLinkComponent={ItemLinkComponent}\n item={item}\n onAddArticle={!isSearching && onAddArticle ? handleAddArticle : undefined}\n isAddingArticle={!isSearching && pendingAddIds.has(item.value.id)}\n isLoadingChildren={!isSearching && item.value.isLoadingChildren}\n onMoreActions={onMoreActions ? (articleId) => onMoreActions(articleId) : undefined}\n {...props}\n />\n )}\n </TreeItemContent>\n\n {!isSearching && item.children && <Collection items={item.children}>{renderItem}</Collection>}\n </TreeItem>\n );\n }}\n </Tree>\n );\n}\n","import type { Key } from 'react-aria-components';\n\nexport function getNewlyExpandedKeys(previous: Iterable<Key>, next: Iterable<Key>): string[] {\n const previousKeys = new Set(Array.from(previous, (key) => key.toString()));\n\n return Array.from(next, (key) => key.toString()).filter((key) => !previousKeys.has(key));\n}\n","import * as React from 'react';\nimport { Article } from '@phosphor-icons/react';\nimport { useDebounceValue } from 'usehooks-ts';\n\nimport { useSidebar } from '../context';\nimport { ArticleNavItem } from '../types';\nimport { ArticleSearch } from './article-search';\nimport { ArticleTree } from './article-tree';\n\nimport { Spinner } from '@/components/ui/spinner';\nimport { cn } from '@/lib/utils';\nimport { Button } from '@/components/ui/button';\nimport { useSubstringFilter } from '@/lib/hooks';\n\n/** Debounce applied to the article tree filter + remount key while searching (avoids work every keystroke). */\nconst ARTICLE_TREE_SEARCH_DEBOUNCE_MS = 400;\n/** Stable ref for useDebounceValue options — inline objects reset debounce each render (usehooks-ts #703). */\nconst ARTICLE_TREE_SEARCH_DEBOUNCE_OPTIONS = { leading: true, trailing: true } as const;\n\nexport interface ArticleNavProps {\n className?: string;\n isLoadingArticles?: boolean;\n articles?: ArticleNavItem[];\n}\n\nexport function ArticleNav({ articles, className, isLoadingArticles }: ArticleNavProps) {\n const { isSearching, searchValue, onAddArticle } = useSidebar();\n const { contains } = useSubstringFilter();\n const trimmedQuery = searchValue.trim();\n const [debouncedTreeQuery] = useDebounceValue(\n isSearching ? trimmedQuery : '',\n isSearching ? ARTICLE_TREE_SEARCH_DEBOUNCE_MS : 0,\n isSearching ? ARTICLE_TREE_SEARCH_DEBOUNCE_OPTIONS : undefined,\n );\n\n const shouldShowLoadingState = !isSearching && (isLoadingArticles ?? articles === undefined);\n const renderLoadingEmptyState = React.useCallback(\n () => (\n <div\n className=\"flex min-h-20 items-center justify-center text-muted-foreground\"\n role=\"status\"\n aria-live=\"polite\"\n aria-label=\"Loading articles list\"\n >\n <Spinner className=\"size-5\" aria-hidden=\"true\" />\n <span className=\"sr-only\">Loading articles list</span>\n </div>\n ),\n [],\n );\n\n const noArticles = !shouldShowLoadingState && !isSearching && (!articles || articles.length === 0);\n\n const filteredArticles = React.useMemo(() => {\n if (isSearching) {\n // `includes('')` is true for every string; avoid showing the full tree with an empty query.\n if (trimmedQuery === '' || debouncedTreeQuery === '') {\n return [];\n }\n const result: ArticleNavItem[] = [];\n const query = debouncedTreeQuery;\n\n const traverse = (nodes: ArticleNavItem[]) => {\n for (const item of nodes) {\n if (contains(item.label, query)) {\n // Strip children so each hit is one row; otherwise the tree would render nested\n // items AND the same nodes again as separate roots (duplicates).\n result.push({ ...item, hasChildren: false, items: [] });\n }\n if (item.items?.length) {\n traverse(item.items);\n }\n }\n };\n\n traverse(articles ?? []);\n\n return result;\n }\n if (articles && articles.length > 0) {\n return articles;\n }\n\n return [];\n }, [articles, isSearching, trimmedQuery, debouncedTreeQuery, contains]);\n\n return (\n <div className={cn('flex flex-col gap-0.5 px-4', className)}>\n {noArticles && (\n <Button variant=\"ghost\" className=\"text-subtlest\" onClick={() => onAddArticle?.(null).catch(() => {})}>\n <Article aria-hidden=\"true\" />\n Create first article or folder\n </Button>\n )}\n\n {shouldShowLoadingState ? (\n <ArticleTree isSearching={isSearching} articles={[]} renderEmptyState={renderLoadingEmptyState} />\n ) : (\n <>\n <ArticleSearch />\n <nav aria-label=\"Articles navigation\">\n <ArticleTree\n key={isSearching ? (trimmedQuery === '' ? 'search:empty' : `search:${debouncedTreeQuery}`) : 'browse'}\n isSearching={isSearching}\n articles={filteredArticles ?? []}\n />\n </nav>\n </>\n )}\n </div>\n );\n}\n","import * as React from 'react';\n\nimport { SidebarNavItem, ArticleNavItem } from './types';\nimport { SidebarContextProps, SidebarProvider } from './context';\nimport { AppNav } from './app-nav';\nimport { ArticleNav } from './article-nav';\n\nimport { ScrollArea } from '@/components/ui/scroll-area';\nimport { cn } from '@/lib/utils';\n\nexport interface SidebarProps extends React.ComponentPropsWithoutRef<'aside'>, SidebarContextProps {\n showAppBack?: boolean;\n onAppBack?: () => void;\n appNavItems?: SidebarNavItem[];\n appNavActiveId?: string;\n showArticles?: boolean;\n isLoadingArticles?: boolean;\n articles?: ArticleNavItem[];\n sectionNavItems?: SidebarNavItem[];\n sectionNavActiveId?: string;\n}\n\nexport const Sidebar = React.forwardRef<HTMLElement, SidebarProps>(function Sidebar(\n {\n className,\n ItemLinkComponent,\n collapsed,\n showAppBack,\n onAppBack,\n appNavItems,\n appNavActiveId,\n isLoadingArticles,\n sectionNavItems,\n sectionNavActiveId,\n activeArticleId,\n showArticles,\n articles,\n onSelectArticle,\n onExpandArticle,\n onSearchArticles,\n onAddArticle,\n onMoreActions,\n canMoveArticle,\n onMoveArticle,\n ...props\n },\n ref,\n) {\n return (\n <SidebarProvider\n collapsed={!!collapsed}\n ItemLinkComponent={ItemLinkComponent}\n activeArticleId={activeArticleId}\n onSelectArticle={onSelectArticle}\n onExpandArticle={onExpandArticle}\n onSearchArticles={onSearchArticles}\n onAddArticle={onAddArticle}\n onMoreActions={onMoreActions}\n canMoveArticle={canMoveArticle}\n onMoveArticle={onMoveArticle}\n >\n <aside\n ref={ref}\n {...props}\n className={cn(\n 'py-4 transition-width duration-200 ease-in-out flex flex-col h-dvh',\n collapsed ? 'w-[64px]' : 'w-[260px]',\n className,\n )}\n aria-label=\"Application navigation\"\n >\n <AppNav\n className={cn(\n 'flex-shrink-0',\n appNavItems && appNavItems.length > 0 && 'pb-4',\n !collapsed && 'border-b border-border-subtle',\n )}\n showBack={showAppBack}\n items={appNavItems}\n activeId={appNavActiveId}\n onBack={onAppBack}\n sectionNavItems={sectionNavItems}\n sectionNavActiveId={sectionNavActiveId}\n />\n\n {!collapsed && (\n <>\n {showArticles && (\n <ScrollArea>\n <ArticleNav\n className=\"py-4 max-w-[var(--left-nav-width,inherit)]\"\n articles={articles}\n isLoadingArticles={isLoadingArticles}\n />\n </ScrollArea>\n )}\n </>\n )}\n </aside>\n </SidebarProvider>\n );\n});\n"],"names":["SidebarContext","React","createContext","SidebarProvider","collapsed","ItemLinkComponent","activeArticleId","onSelectArticle","onExpandArticle","onSearchArticles","onAddArticle","onMoreActions","canMoveArticle","onMoveArticle","children","isSearching","setIsSearching","useState","searchValue","setSearchValue","lastSelectedArticleId","setLastSelectedArticleId","handleSearchArticles","useCallback","value","trimmedValue","trim","contextValue","useMemo","Provider","useSidebar","sidebarContext","useContext","Error","SectionNav","className","items","activeId","createElement","cn","map","item","key","id","href","label","AppNav","showBack","onBack","sectionNavItems","sectionNavActiveId","hasBack","Button","variant","size","onClick","ArrowBendUpLeft","ScrollArea","Fragment","Icon","weight","length","ArticleSearch","searchInteracted","setSearchInteracted","useToggle","searchInputRef","useRef","useEffect","Input","ref","startIcon","MagnifyingGlass","endIcon","X","onEndIconClick","onChange","e","target","placeholder","type","FolderSlotButton","AriaButton","slot","ArticleItem","hasChildItems","isSelected","isExpanded","isAddingArticle","isLoadingChildren","level","treeState","TreeStateContext","shouldPreventNavigation","Boolean","showActions","isDraft","status","statusLabel","folderIcon","Folder","FolderOpen","folderWithChangesIcon","FolderDashed","discoveryIconContent","Lightning","discoveryIcon","fileIcon","File","fileWithChangesIcon","FileDashed","loadingFolderIcon","role","Spinner","style","Array","from","_","i","hasChanges","renderStatusIcon","title","preventDefault","stopPropagation","toggleKey","ButtonGroup","orientation","DotsThree","Plus","flattenArticles","parentId","depth","result","forEach","index","push","placeholderCounter","getParentKeys","targetId","parents","treeNodesToArticleNavItems","ArticleTree","articles","renderEmptyState","effectiveActiveId","articlesTree","useTreeData","initialItems","getKey","articleItem","getChildren","prevArticlesRef","current","operations","currentArticles","nextArticles","currentEntries","nextEntries","currentMap","Map","entry","nextMap","filter","has","sort","a","b","currentEntry","get","hasChildren","buildArticleTreeSyncOperations","operation","remove","insert","move","update","dragAndDropHooks","useDragAndDrop","getItems","_keys","onMove","movedArticleId","keys","targetItem","getItem","movedToParentId","movedToIndex","dropPosition","toString","parentKey","targetIndex","findIndex","moveDetails","movedItem","originalParentId","originalIndex","moveBefore","moveAfter","then","catch","renderDropIndicator","DropIndicator","localSelectedKeys","setLocalSelectedKeys","Set","selectedKeys","pathToActive","expandedKeysState","setExpandedKeysState","expandedKeys","pendingAddIdsRef","pendingAddIds","setPendingAddIds","handleAddArticle","add","tempId","append","prev","created","delete","navigateToArticleId","articleId","Tree","selectionBehavior","selectionMode","onExpandedChange","nextExpandedKeys","previous","next","previousKeys","getNewlyExpandedKeys","disallowEmptySelection","onSelectionChange","selection","selected","renderItem","TreeItem","textValue","TreeItemContent","props","Collection","ARTICLE_TREE_SEARCH_DEBOUNCE_OPTIONS","leading","trailing","ArticleNav","isLoadingArticles","contains","useSubstringFilter","trimmedQuery","debouncedTreeQuery","useDebounceValue","shouldShowLoadingState","renderLoadingEmptyState","noArticles","filteredArticles","query","traverse","nodes","Article","Sidebar","forwardRef","showAppBack","onAppBack","appNavItems","appNavActiveId","showArticles"],"mappings":"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"}
@@ -1,11 +1,11 @@
1
- import*as e from"react";import t,{useState as a,useCallback as s,useMemo as l,useContext as n,createContext as r,forwardRef as c}from"react";import{Circle as i,CheckCircle as o,XCircle as m,CaretUp as d,CaretDown as u}from"@phosphor-icons/react";import{c as f}from"./utils.C6Qu-kwd.js";import{b as p}from"./formatDate.D2xEZm8f.js";import{S as x}from"./status-badge.BLB0pWDn.js";import{B as g,a as b}from"./button.D_2SonNs.js";import{ScrollArea as E}from"../components/ui/scroll-area.js";function N({count:e}){/* @__PURE__ */
2
- return t.createElement("span",{className:"inline-flex items-center gap-0.5"},/* @__PURE__ */t.createElement(i,{size:8,weight:"fill","aria-hidden":"true",className:"text-blue"}),/* @__PURE__ */t.createElement("span",{className:"text-xs leading-4 text-subtle"},e," ",1===e?"edit":"edits"))}const h=e.forwardRef(function({title:t,timestamp:a,icon:s,description:l,isNew:n,isAccepted:r,editCount:c,isSelected:i=!1,className:o,...m},d){let u;return r?u=/* @__PURE__ */e.createElement(x,{variant:"accepted"},"Accepted"):c&&(u=/* @__PURE__ */e.createElement(N,{count:c})),/* @__PURE__ */e.createElement("button",{...m,ref:d,type:"button","aria-pressed":i,className:f("relative flex w-full flex-col gap-1 bg-surface rounded p-4 cursor-pointer transition-colors text-left border border-transparent",i?["shadow-[0px_1px_3px_0px_rgba(95,95,95,0.26)]",'after:content-[""] after:block after:absolute after:right-[-2px] after:top-1/2 after:-translate-y-1/2 after:w-1 after:h-14 after:rounded-sm after:bg-primary']:"hover:bg-dark-100 hover:border-dark-300",o)},
3
- /* @__PURE__ */e.createElement("span",{className:"flex items-center justify-between w-full gap-2"},/* @__PURE__ */e.createElement("span",{className:f("text-sm text-default truncate min-w-0 flex-1",i?"font-bold":"font-normal")},t),a&&/* @__PURE__ */e.createElement("span",{className:"text-xs leading-4 text-subtlest shrink-0"},p(a))),(s||l||u)&&/* @__PURE__ */e.createElement("span",{className:"flex items-center gap-1 leading-4"},n&&/* @__PURE__ */e.createElement(x,{variant:"success",surface:"transparent"},"New"),s&&/* @__PURE__ */e.createElement("span",{className:"shrink-0 flex items-center"},s),l&&/* @__PURE__ */e.createElement("span",{className:"text-xs text-subtle truncate"},l),!n&&u&&/* @__PURE__ */e.createElement("span",{className:"shrink-0 ml-1 flex items-center"},u)))}),v=r(null);function w({children:e,defaultSelectedItem:n=null,onApproveAllSuggestions:r,onRejectAllSuggestions:c,onAcceptAndPublish:i,onOpenArticleLink:o,onSourceLinkClick:m,breadcrumb:d,suggestionReasonBody:u}){const[f,p]=a(null),x=f??n,[g,b]=a(null),[E,N]=a(!1),h=s(e=>p(e),[]),w=l(()=>({selectedItem:x,setSelectedItem:h,loadedDiffDoc:g,setLoadedDiffDoc:b,loadingDiff:E,setLoadingDiff:N,onApproveAllSuggestions:r,onRejectAllSuggestions:c,onAcceptAndPublish:i,onOpenArticleLink:o,onSourceLinkClick:m,breadcrumb:d,suggestionReasonBody:u}),[x,h,g,E,r,c,i,o,m,d,u]);/* @__PURE__ */
4
- return t.createElement(v.Provider,{value:w},e)}function k(){const e=n(v);if(!e)throw new Error("useReviewsSelection must be used within ReviewsSelectionProvider");return e}const y=c(({items:e,className:a,...s},l)=>{const{selectedItem:n,setSelectedItem:r}=k();/* @__PURE__ */
5
- return t.createElement("ul",{ref:l,className:f("min-w-0 w-full overflow-hidden bg-muted border border-dark-300 rounded-lg p-2 space-y-2 list-none m-0",a),...s},e.map(e=>/* @__PURE__ */t.createElement("li",{key:e.id},/* @__PURE__ */t.createElement(h,{...e,isSelected:n?.id===e.id,onClick:()=>r(e)}))))});y.displayName="ReviewList";const A=e.forwardRef(function({source:t,diff:a,reason:s,onAccept:l,onReject:n,acceptDisabled:r,rejectDisabled:c,pagination:i,className:d,readOnly:u,...p},x){const N=r||!l,h=c||!n,v=Boolean(a&&a.oldText&&a.newText);/* @__PURE__ */
6
- return e.createElement("div",{ref:x,role:"group","aria-label":"Review suggestion",className:f("grid h-[calc(var(--knowledge-review-scroll-height)-250px)] w-full items-stretch gap-4 rounded-lg bg-surface p-4 border shadow-md dark:shadow-brand-dark",d),...p},
1
+ import*as e from"react";import t,{useState as a,useCallback as s,useMemo as l,useContext as n,createContext as r,forwardRef as i}from"react";import{Circle as c,CheckCircle as o,XCircle as m,CaretUp as d,CaretDown as u}from"@phosphor-icons/react";import{c as f}from"./utils.C6Qu-kwd.js";import{b as p}from"./formatDate.D2xEZm8f.js";import{S as x}from"./status-badge.BLB0pWDn.js";import{B as g,a as b}from"./button.D_2SonNs.js";import{ScrollArea as E}from"../components/ui/scroll-area.js";function N({count:e}){/* @__PURE__ */
2
+ return t.createElement("span",{className:"inline-flex items-center gap-0.5"},/* @__PURE__ */t.createElement(c,{size:8,weight:"fill","aria-hidden":"true",className:"text-blue"}),/* @__PURE__ */t.createElement("span",{className:"text-xs leading-4 text-subtle"},e," ",1===e?"edit":"edits"))}const h=e.forwardRef(function({title:t,timestamp:a,icon:s,description:l,isNew:n,isAccepted:r,editCount:i,isSelected:c=!1,className:o,...m},d){let u;return r?u=/* @__PURE__ */e.createElement(x,{variant:"accepted"},"Accepted"):i&&(u=/* @__PURE__ */e.createElement(N,{count:i})),/* @__PURE__ */e.createElement("button",{...m,ref:d,type:"button","aria-pressed":c,className:f("relative flex w-full flex-col gap-1 bg-surface rounded p-4 cursor-pointer transition-colors text-left border border-transparent",c?["shadow-[0px_1px_3px_0px_rgba(95,95,95,0.26)]",'after:content-[""] after:block after:absolute after:right-[-2px] after:top-1/2 after:-translate-y-1/2 after:w-1 after:h-14 after:rounded-sm after:bg-primary']:"hover:bg-dark-100 hover:border-dark-300",o)},
3
+ /* @__PURE__ */e.createElement("span",{className:"flex items-center justify-between w-full gap-2"},/* @__PURE__ */e.createElement("span",{className:f("text-sm text-default truncate min-w-0 flex-1",c?"font-bold":"font-normal")},t),a&&/* @__PURE__ */e.createElement("span",{className:"text-xs leading-4 text-subtlest shrink-0"},p(a))),(s||l||u)&&/* @__PURE__ */e.createElement("span",{className:"flex items-center gap-1 leading-4"},n&&/* @__PURE__ */e.createElement(x,{variant:"success",surface:"transparent"},"New"),s&&/* @__PURE__ */e.createElement("span",{className:"shrink-0 flex items-center"},s),l&&/* @__PURE__ */e.createElement("span",{className:"text-xs text-subtle truncate"},l),!n&&u&&/* @__PURE__ */e.createElement("span",{className:"shrink-0 ml-1 flex items-center"},u)))}),v=r(null);function w({children:e,defaultSelectedItem:n=null,onApproveAllSuggestions:r,onRejectAllSuggestions:i,onAcceptAndPublish:c,onOpenArticleLink:o,onSourceLinkClick:m,breadcrumb:d,suggestionReasonBody:u}){const[f,p]=a(null),x=f??n,[g,b]=a(null),[E,N]=a(!1),h=s(e=>p(e),[]),w=l(()=>({selectedItem:x,setSelectedItem:h,loadedDiffDoc:g,setLoadedDiffDoc:b,loadingDiff:E,setLoadingDiff:N,onApproveAllSuggestions:r,onRejectAllSuggestions:i,onAcceptAndPublish:c,onOpenArticleLink:o,onSourceLinkClick:m,breadcrumb:d,suggestionReasonBody:u}),[x,h,g,E,r,i,c,o,m,d,u]);/* @__PURE__ */
4
+ return t.createElement(v.Provider,{value:w},e)}function k(){const e=n(v);if(!e)throw new Error("useReviewsSelection must be used within ReviewsSelectionProvider");return e}const y=i(({items:e,className:a,...s},l)=>{const{selectedItem:n,setSelectedItem:r}=k();/* @__PURE__ */
5
+ return t.createElement("ul",{ref:l,className:f("min-w-0 w-full overflow-hidden bg-muted border border-dark-300 rounded-lg p-2 space-y-2 list-none m-0",a),...s},e.map(e=>/* @__PURE__ */t.createElement("li",{key:e.id},/* @__PURE__ */t.createElement(h,{...e,isSelected:n?.id===e.id,onClick:()=>r(e)}))))});y.displayName="ReviewList";const A=e.forwardRef(function({source:t,diff:a,reason:s,onAccept:l,onReject:n,acceptDisabled:r,rejectDisabled:i,pagination:c,className:d,readOnly:u,...p},x){const N=r||!l,h=i||!n,v=Boolean(a&&a.oldText&&a.newText);/* @__PURE__ */
6
+ return e.createElement("div",{ref:x,role:"group","aria-label":"Review suggestion",className:f("!grid max-h-[calc(var(--knowledge-review-scroll-height)-250px)] w-full grid-rows-[auto_minmax(0,1fr)_auto] items-stretch gap-4 rounded-lg bg-surface p-4 border shadow-md dark:shadow-brand-dark",d),...p},
7
7
  /* @__PURE__ */e.createElement("div",{className:"flex min-w-0 flex-col justify-start gap-1"},t&&/* @__PURE__ */e.createElement(e.Fragment,null,/* @__PURE__ */e.createElement("span",{className:"text-xs font-bold uppercase leading-4 text-default"},t.label),/* @__PURE__ */e.createElement("div",{className:"flex items-center gap-0.5 [&_svg]:size-4 [&_svg]:shrink-0"},/* @__PURE__ */e.createElement("span",{className:"flex items-center text-subtle","aria-hidden":"true"},t.icon),/* @__PURE__ */e.createElement("span",{className:"text-sm leading-4 text-subtle break-all"},t.name)))),
8
- /* @__PURE__ */e.createElement("div",{className:"flex min-w-0 min-h-0 items-stretch gap-2"},/* @__PURE__ */e.createElement(E,{className:"-mr-2 min-h-0 flex-1 pr-2"},/* @__PURE__ */e.createElement("div",{className:"flex w-full flex-col gap-4"},/* @__PURE__ */e.createElement("span",{className:"text-xs font-bold uppercase leading-4 text-default"},"Reason"),s&&/* @__PURE__ */e.createElement("span",{className:"text-sm leading-4 text-default"},s),v&&/* @__PURE__ */e.createElement(S,{oldText:a?.oldText,newText:a?.newText}))),i&&i.totalCount>1&&/* @__PURE__ */e.createElement(R,{...i})),
8
+ /* @__PURE__ */e.createElement("div",{className:"flex min-w-0 min-h-0 items-stretch gap-2"},/* @__PURE__ */e.createElement(E,{className:"-mr-2 min-h-0 flex-1 pr-2"},/* @__PURE__ */e.createElement("div",{className:"flex w-full flex-col gap-4"},/* @__PURE__ */e.createElement("span",{className:"text-xs font-bold uppercase leading-4 text-default"},"Reason"),s&&/* @__PURE__ */e.createElement("span",{className:"text-sm leading-4 text-default"},s),v&&/* @__PURE__ */e.createElement(S,{oldText:a?.oldText,newText:a?.newText}))),c&&c.totalCount>1&&/* @__PURE__ */e.createElement(R,{...c})),
9
9
  /* @__PURE__ */e.createElement("div",{className:"flex min-w-0 items-end"},!u&&/* @__PURE__ */e.createElement("div",{className:"flex shrink-0 items-center gap-2"},!N&&/* @__PURE__ */e.createElement(g,{type:"button",variant:"default",elevation:"shadow",size:"icon",onClick:l,"aria-label":"Accept suggestion",className:f("rounded-md border-border bg-green-400 text-default",b)},
10
10
  /* @__PURE__ */e.createElement(o,{weight:"regular","aria-hidden":"true"})),!h&&/* @__PURE__ */e.createElement(g,{type:"button",variant:"destructive",elevation:"shadow",size:"icon",onClick:n,"aria-label":"Reject suggestion",className:f("rounded-md border-border bg-red-400 text-default",b)},
11
11
  /* @__PURE__ */e.createElement(m,{weight:"regular","aria-hidden":"true"})))))});function S({oldText:t,newText:a}){/* @__PURE__ */
@@ -13,4 +13,4 @@ return e.createElement("div",{className:"flex flex-col items-baseline gap-2 bord
13
13
  return e.createElement("div",{className:"flex w-10 shrink-0 flex-col items-center justify-center self-stretch py-2 pl-3"},/* @__PURE__ */e.createElement("div",{className:"flex flex-col items-center gap-0.5"},/* @__PURE__ */e.createElement(g,{type:"button",variant:"ghost",size:"icon",onClick:s,disabled:!n,"aria-label":"Previous suggestion",className:"text-subtlest disabled:invisible"},
14
14
  /* @__PURE__ */e.createElement(d,{"aria-hidden":"true",className:"size-3.5"})),/* @__PURE__ */e.createElement("span",{className:"text-xs leading-4 text-subtlest tabular-nums","aria-hidden":"true"},t,"/",a),/* @__PURE__ */e.createElement("span",{className:"sr-only","aria-live":"polite"},"Suggestion ",t," of ",a),/* @__PURE__ */e.createElement(g,{type:"button",variant:"ghost",size:"icon",onClick:l,disabled:!r,"aria-label":"Next suggestion",className:"text-subtlest disabled:invisible"},
15
15
  /* @__PURE__ */e.createElement(u,{"aria-hidden":"true",className:"size-3.5"}))))}export{N as E,y as R,A as S,h as a,w as b,k as u};
16
- //# sourceMappingURL=suggestion-card.ByBVw527.js.map
16
+ //# sourceMappingURL=suggestion-card.27D75y9M.js.map