@hyddenlabs/hydn-ui 0.3.16 → 0.3.18

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.
Files changed (24) hide show
  1. package/dist/components/feedback/error-page/error-400.js +1 -1
  2. package/dist/components/feedback/error-page/error-401.js +1 -1
  3. package/dist/components/feedback/error-page/error-403.js +1 -1
  4. package/dist/components/feedback/error-page/error-404.js +1 -1
  5. package/dist/components/forms/button/button-with-icon.js +1 -1
  6. package/dist/components/forms/button/icon-button.js +1 -1
  7. package/dist/components/layout/left-nav-layout/left-nav-item.d.ts +6 -3
  8. package/dist/components/layout/left-nav-layout/left-nav-item.d.ts.map +1 -1
  9. package/dist/components/layout/left-nav-layout/left-nav-item.js +38 -17
  10. package/dist/components/layout/left-nav-layout/left-nav-item.js.map +1 -1
  11. package/dist/components/layout/left-nav-layout/left-nav-layout.d.ts +27 -21
  12. package/dist/components/layout/left-nav-layout/left-nav-layout.d.ts.map +1 -1
  13. package/dist/components/layout/left-nav-layout/left-nav-layout.js +140 -94
  14. package/dist/components/layout/left-nav-layout/left-nav-layout.js.map +1 -1
  15. package/dist/components/layout/left-nav-layout/left-nav-section.d.ts.map +1 -1
  16. package/dist/components/layout/left-nav-layout/left-nav-section.js +10 -10
  17. package/dist/components/layout/left-nav-layout/left-nav-section.js.map +1 -1
  18. package/dist/components/navigation/dropdown/dropdown.js +1 -1
  19. package/dist/components/navigation/navbar/navbar.js +2 -2
  20. package/dist/components/navigation/navbar/navbar.js.map +1 -1
  21. package/dist/style.css +1 -1
  22. package/dist/theme/tokens.js +2 -2
  23. package/dist/theme/tokens.js.map +1 -1
  24. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"left-nav-layout.js","sources":["../../../../src/components/layout/left-nav-layout/left-nav-layout.tsx"],"sourcesContent":["import { ReactNode, useState, useRef, useEffect } from 'react';\nimport useScrollReset from '@/hooks/useScrollReset';\nimport { Icon } from '../../system/icon/icon';\n\nexport type LeftNavLayoutProps = {\n /** Navigation sidebar content */\n nav: ReactNode;\n /** Main content area */\n children: ReactNode;\n /** Custom className for the layout container */\n className?: string;\n /** Custom className for the nav sidebar */\n navClassName?: string;\n /** Custom className for the content area */\n contentClassName?: string;\n /** Width of the sidebar */\n navWidth?: string;\n /** Hide navigation on mobile (slides in as overlay when toggled) */\n hideOnMobile?: boolean;\n /** Embedded demo mode (no fixed positioning, constrained height) */\n embedded?: boolean;\n /** Ref for the main content scrollable element */\n mainContentRef?: React.RefObject<HTMLDivElement>;\n /** Logo or brand content rendered in the sidebar header */\n logo?: ReactNode;\n /** Content pinned to the bottom of the sidebar (e.g. profile, logout actions) */\n bottomContent?: ReactNode;\n /** Optional bar rendered above the main content area, to the right of the sidebar */\n topbar?: ReactNode;\n};\n\n/**\n * LeftNavLayout - Fixed-width left navigation sidebar layout\n *\n * Provides a sidebar navigation with:\n * - Fixed width (always visible, no collapse)\n * - Logo/brand header slot\n * - Scrollable nav area\n * - Pinned bottom content slot\n * - Optional mobile overlay mode\n *\n * @example\n * ```tsx\n * <LeftNavLayout\n * logo={<img src=\"/logo.png\" alt=\"Logo\" className=\"h-8\" />}\n * nav={\n * <>\n * <LeftNavItem icon=\"home\" href=\"/\">Home</LeftNavItem>\n * <LeftNavItem icon=\"dashboard\" href=\"/dashboard\">Dashboard</LeftNavItem>\n * </>\n * }\n * bottomContent={\n * <LeftNavItem icon=\"logout\" onClick={logout}>Logout</LeftNavItem>\n * }\n * >\n * <main>Your content here</main>\n * </LeftNavLayout>\n * ```\n */\nfunction LeftNavLayout({\n nav,\n children,\n className = '',\n navClassName = '',\n contentClassName = '',\n navWidth = 'w-26',\n hideOnMobile = false,\n embedded = false,\n mainContentRef,\n logo,\n bottomContent,\n topbar\n}: Readonly<LeftNavLayoutProps>) {\n const [mobileMenuOpen, setMobileMenuOpen] = useState(!hideOnMobile);\n const [showScrollDown, setShowScrollDown] = useState(false);\n const [showScrollUp, setShowScrollUp] = useState(false);\n\n const closeMobileMenu = () => setMobileMenuOpen(false);\n\n const navRef = useRef<HTMLDivElement | null>(null);\n const scrollPosRef = useRef<number>(0);\n const internalContentRef = useRef<HTMLElement | null>(null);\n const contentRef = mainContentRef || internalContentRef;\n\n // Restore nav scroll position after children change (route switch) & reset scroll\n useEffect(() => {\n if (navRef.current) {\n navRef.current.scrollTop = scrollPosRef.current;\n }\n }, [children]);\n\n // Robust scroll reset for main content area on children change\n // Pass the ref object (not .current) to avoid reading ref during render\n useScrollReset([children], contentRef as React.RefObject<HTMLElement | null>);\n\n const updateScrollDirection = () => {\n const el = navRef.current;\n if (!el) return;\n setShowScrollDown(el.scrollHeight > el.clientHeight && el.scrollTop < el.scrollHeight - el.clientHeight - 4);\n setShowScrollUp(el.scrollTop > 50);\n };\n\n const scrollDown = () => {\n const el = navRef.current;\n if (!el) return;\n el.scrollBy({ top: el.clientHeight * 0.75, behavior: 'smooth' });\n };\n\n const scrollUp = () => {\n const el = navRef.current;\n if (!el) return;\n el.scrollBy({ top: -el.clientHeight * 0.75, behavior: 'smooth' });\n };\n\n useEffect(() => {\n updateScrollDirection();\n const el = navRef.current;\n if (!el) return;\n const ro = new ResizeObserver(updateScrollDirection);\n ro.observe(el);\n return () => ro.disconnect();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [nav]);\n\n useEffect(() => {\n updateScrollDirection();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const containerClasses = embedded\n ? 'flex bg-background border border-border rounded-lg overflow-hidden'\n : 'fixed inset-0 flex overflow-hidden bg-background';\n\n return (\n <div className={`${containerClasses} ${className}`}>\n {/* Mobile Backdrop Overlay - Only shows on mobile when menu is open */}\n {!embedded && hideOnMobile && mobileMenuOpen && (\n <div\n className=\"fixed inset-0 bg-black/50 z-30 lg:hidden transition-opacity duration-300\"\n onClick={closeMobileMenu}\n aria-hidden=\"true\"\n />\n )}\n\n {/* Sidebar Navigation */}\n <aside\n className={`${\n embedded\n ? 'relative flex flex-col h-full'\n : hideOnMobile\n ? 'fixed lg:relative top-0 left-0 z-40 lg:z-10 h-screen lg:h-full'\n : 'relative h-full'\n } flex flex-col shrink-0 bg-[#24273D] ${\n !embedded && hideOnMobile && !mobileMenuOpen ? '-translate-x-full lg:translate-x-0' : 'translate-x-0'\n } ${navWidth} ${navClassName}`}\n aria-label=\"Main navigation\"\n >\n {/* Logo / Brand Header */}\n {logo && (\n <div className=\"h-16 bg-[#151823] flex items-center justify-center border-b border-[#2e3148] shadow-sm shrink-0 px-4\">\n {logo}\n </div>\n )}\n\n {/* Nav Content - Scrollable */}\n <div className=\"relative flex-1 min-h-0 flex flex-col\">\n <nav\n ref={navRef}\n className=\"flex-1 overflow-y-auto divide-y divide-muted-foreground scrollbar-dark\"\n onScroll={(e) => {\n scrollPosRef.current = (e.currentTarget as HTMLDivElement).scrollTop;\n updateScrollDirection();\n }}\n >\n {nav}\n </nav>\n\n {/* Scroll-down indicator */}\n {showScrollDown && (\n <button\n onClick={scrollDown}\n className=\"group absolute bottom-0 left-0 right-0 h-16 flex items-end justify-center pb-2 cursor-pointer z-10\"\n aria-label=\"Scroll down\"\n >\n <div className=\"absolute inset-0 bg-linear-to-t from-[#24273D] via-[#24273D]/90 to-transparent\" />\n <div className=\"relative transition-transform duration-150 group-hover:translate-y-0.5 pr-2.5\">\n <Icon name=\"chevron-down\" size=\"md\" color=\"neutral\" />\n </div>\n </button>\n )}\n {showScrollUp && (\n <button\n onClick={scrollUp}\n className=\"group absolute top-0 left-0 right-0 h-16 flex items-start justify-center pt-2 cursor-pointer z-10\"\n aria-label=\"Scroll up\"\n >\n <div className=\"absolute inset-0 bg-linear-to-b from-[#24273D] via-[#24273D]/90 to-transparent\" />\n <div className=\"relative transition-transform duration-150 group-hover:-translate-y-0.5 pr-2.5\">\n <Icon name=\"chevron-up\" size=\"md\" color=\"neutral\" />\n </div>\n </button>\n )}\n </div>\n\n {/* Bottom Pinned Section */}\n {bottomContent && <div className=\"border-t border-[#2e3148] shrink-0\">{bottomContent}</div>}\n </aside>\n\n {/* Right side: topbar + main content */}\n <div className=\"flex-1 flex flex-col overflow-hidden\">\n {topbar && <div className=\"shrink-0\">{topbar}</div>}\n\n {/* Main Content Area */}\n <main\n ref={contentRef as React.RefObject<HTMLDivElement>}\n className={`flex-1 overflow-y-auto ${embedded ? 'h-60' : ''} ${contentClassName}`}\n >\n {children}\n </main>\n </div>\n </div>\n );\n}\n\nLeftNavLayout.displayName = 'LeftNavLayout';\n\nexport default LeftNavLayout;\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"left-nav-layout.js","sources":["../../../../src/components/layout/left-nav-layout/left-nav-layout.tsx"],"sourcesContent":["import { ReactNode, useState, useRef, useEffect, useLayoutEffect } from 'react';\nimport useScrollReset from '@/hooks/useScrollReset';\nimport LeftNavItem from './left-nav-item';\n\nexport type LeftNavLayoutProps = {\n /** Navigation sidebar content */\n nav: ReactNode;\n /** Main content area */\n children: ReactNode;\n /** Whether sidebar is collapsed (icon-only mode) */\n collapsed?: boolean;\n /** Callback when collapse state changes */\n onCollapsedChange?: (collapsed: boolean) => void;\n /** Whether to show collapse toggle button */\n showToggle?: boolean;\n /** Custom className for the layout container */\n className?: string;\n /** Custom className for the nav sidebar */\n navClassName?: string;\n /** Custom className for the content area */\n contentClassName?: string;\n /** Width of the sidebar when expanded */\n navWidth?: string;\n /** Width of the sidebar when collapsed */\n navWidthCollapsed?: string;\n /** Hide navigation on mobile (slides in as overlay when toggled) */\n hideOnMobile?: boolean;\n /** Auto-collapse to icon-only mode on mobile screens */\n autoCollapseOnMobile?: boolean;\n /** Embedded demo mode (no fixed positioning, constrained height) */\n embedded?: boolean;\n /** Ref for the main content scrollable element */\n mainContentRef?: React.RefObject<HTMLDivElement>;\n /** Optional header text for the navigation sidebar */\n header?: string;\n};\n\n/**\n * LeftNavLayout - Full-featured responsive left navigation layout\n *\n * Provides a robust sidebar navigation with:\n * - Full and collapsed (icon-only) states\n * - Smooth transitions without janky spacing\n * - Proper scroll handling\n * - Responsive mobile behavior\n * - Accessible keyboard navigation\n *\n * @example\n * ```tsx\n * <LeftNavLayout\n * collapsed={isCollapsed}\n * onCollapsedChange={setIsCollapsed}\n * nav={\n * <>\n * <LeftNavSection>\n * <LeftNavItem icon={<HomeIcon />} href=\"/\" active>Home</LeftNavItem>\n * <LeftNavItem icon={<DashboardIcon />} href=\"/dashboard\">Dashboard</LeftNavItem>\n * </LeftNavSection>\n * </>\n * }\n * >\n * <main>Your content here</main>\n * </LeftNavLayout>\n * ```\n */\nfunction LeftNavLayout({\n nav,\n children,\n collapsed: controlledCollapsed,\n onCollapsedChange,\n showToggle = true,\n className = '',\n navClassName = '',\n contentClassName = '',\n navWidth = '16rem',\n navWidthCollapsed = '4.5rem',\n hideOnMobile = false,\n autoCollapseOnMobile = true,\n embedded = false,\n header = 'Navigation',\n mainContentRef\n}: Readonly<LeftNavLayoutProps>) {\n const STORAGE_KEY_DESKTOP = 'left-nav-desktop-collapsed';\n const STORAGE_KEY_MOBILE = 'left-nav-mobile-collapsed';\n\n // Initialize desktop collapsed state from localStorage (defaults to false = expanded)\n const [internalCollapsed, setInternalCollapsed] = useState(() => {\n if (typeof window === 'undefined') return false;\n try {\n const saved = localStorage.getItem(STORAGE_KEY_DESKTOP);\n return saved !== null ? saved === 'true' : false;\n } catch (error) {\n // eslint-disable-next-line no-console\n console.warn('Failed to read desktop collapsed state from localStorage:', error);\n return false;\n }\n });\n\n const [mobileMenuOpen, setMobileMenuOpen] = useState(!hideOnMobile);\n const [isMobile, setIsMobile] = useState(() => window.innerWidth < 1024);\n\n // Initialize mobile collapsed state from localStorage (defaults to true = collapsed)\n const [mobileCollapsedOverride, setMobileCollapsedOverride] = useState<boolean | null>(() => {\n if (typeof window === 'undefined') return null;\n try {\n const saved = localStorage.getItem(STORAGE_KEY_MOBILE);\n // If user has never toggled, return null to use default (collapsed)\n // If they have toggled, use their saved preference\n return saved !== null ? saved === 'true' : null;\n } catch (error) {\n // eslint-disable-next-line no-console\n console.warn('Failed to read mobile collapsed state from localStorage:', error);\n return null;\n }\n });\n\n const desktopCollapsedRef = useRef<boolean | undefined>(undefined);\n\n const navRef = useRef<HTMLDivElement | null>(null);\n const scrollPosRef = useRef<number>(0);\n const internalContentRef = useRef<HTMLElement | null>(null);\n const contentRef = mainContentRef || internalContentRef;\n\n // Detect mobile screen size\n // Use useLayoutEffect to run synchronously before paint, preventing layout shift\n useLayoutEffect(() => {\n const checkMobile = () => {\n const newIsMobile = window.innerWidth < 1024; // lg breakpoint\n if (newIsMobile !== isMobile) {\n const wasDesktop = !isMobile;\n const isNowDesktop = !newIsMobile;\n\n setIsMobile(newIsMobile);\n\n // When switching from desktop to mobile, save the desktop state\n if (wasDesktop && autoCollapseOnMobile) {\n const currentCollapsed = controlledCollapsed ?? internalCollapsed;\n desktopCollapsedRef.current = currentCollapsed;\n }\n\n // When switching from mobile to desktop, restore the desktop state\n if (isNowDesktop && autoCollapseOnMobile && desktopCollapsedRef.current !== undefined) {\n if (controlledCollapsed === undefined) {\n // Only restore if using uncontrolled state\n setInternalCollapsed(desktopCollapsedRef.current);\n }\n }\n\n // When switching to mobile, restore mobile state from localStorage\n if (!isNowDesktop && autoCollapseOnMobile) {\n try {\n const savedMobile = localStorage.getItem(STORAGE_KEY_MOBILE);\n setMobileCollapsedOverride(savedMobile !== null ? savedMobile === 'true' : null);\n } catch {\n setMobileCollapsedOverride(null);\n }\n } else if (isNowDesktop) {\n // When switching to desktop, clear mobile override (not needed on desktop)\n setMobileCollapsedOverride(null);\n }\n }\n };\n\n checkMobile();\n window.addEventListener('resize', checkMobile);\n return () => window.removeEventListener('resize', checkMobile);\n }, [isMobile, autoCollapseOnMobile, controlledCollapsed, internalCollapsed]);\n\n // Use controlled or uncontrolled collapsed state\n const collapsed = controlledCollapsed ?? internalCollapsed;\n const setCollapsed = (value: boolean) => {\n if (onCollapsedChange) {\n onCollapsedChange(value);\n } else {\n setInternalCollapsed(value);\n // Persist desktop state to localStorage\n try {\n localStorage.setItem(STORAGE_KEY_DESKTOP, String(value));\n } catch (error) {\n // eslint-disable-next-line no-console\n console.warn('Failed to save desktop collapsed state to localStorage:', error);\n }\n }\n };\n\n // Determine effective collapsed state\n // On mobile with autoCollapseOnMobile: use override if set, otherwise default to collapsed\n // On desktop or without autoCollapseOnMobile: use normal collapsed state\n const effectiveCollapsed =\n autoCollapseOnMobile && isMobile ? (mobileCollapsedOverride !== null ? mobileCollapsedOverride : true) : collapsed;\n\n const toggleCollapsed = () => setCollapsed(!collapsed);\n const closeMobileMenu = () => setMobileMenuOpen(false);\n\n // On mobile with hideOnMobile, toggle closes the overlay; on desktop, it collapses\n // On mobile with autoCollapseOnMobile, toggle the mobile override state\n const handleToggleClick = () => {\n if (hideOnMobile && isMobile) {\n // Hide on mobile mode - close the overlay\n closeMobileMenu();\n } else if (autoCollapseOnMobile && isMobile) {\n // Auto-collapse mode - toggle the mobile override\n const newMobileState = !effectiveCollapsed;\n setMobileCollapsedOverride(newMobileState);\n // Persist mobile state to localStorage\n try {\n localStorage.setItem(STORAGE_KEY_MOBILE, String(newMobileState));\n } catch {\n // eslint-disable-next-line no-console\n console.warn('Failed to save mobile collapsed state to localStorage:');\n }\n } else {\n // Desktop or normal mode - toggle regular collapsed state\n toggleCollapsed();\n }\n };\n\n // Restore nav scroll position after children change (route switch) & reset scroll\n useEffect(() => {\n if (navRef.current) {\n navRef.current.scrollTop = scrollPosRef.current;\n }\n }, [children]);\n\n // Robust scroll reset for main content area on children change\n // Pass the ref object (not .current) to avoid reading ref during render\n useScrollReset([children], contentRef as React.RefObject<HTMLElement | null>);\n\n const containerClasses = embedded\n ? 'flex bg-background border border-border rounded-lg overflow-hidden'\n : 'flex h-[calc(100vh-3.5rem)] md:h-[calc(100vh-4rem)] bg-background';\n\n return (\n <div className={`${containerClasses} ${className}`}>\n {/* Mobile Backdrop Overlay - Only shows on mobile when menu is open */}\n {!embedded && hideOnMobile && mobileMenuOpen && (\n <div\n className=\"fixed inset-0 bg-black/50 z-30 lg:hidden transition-opacity duration-300\"\n onClick={closeMobileMenu}\n aria-hidden=\"true\"\n />\n )}\n\n {/* Sidebar Navigation */}\n <aside\n className={`${embedded ? 'relative flex flex-col h-full' : hideOnMobile ? 'fixed lg:relative top-14 md:top-16 lg:top-0 left-0 z-40 lg:z-10 h-[calc(100vh-3.5rem)] md:h-[calc(100vh-4rem)] lg:h-full' : 'relative h-full'} flex flex-col shrink-0 bg-background border-r border-border transition-all duration-300 ease-in-out ${!embedded && hideOnMobile && !mobileMenuOpen ? '-translate-x-full lg:translate-x-0' : 'translate-x-0'} ${effectiveCollapsed ? 'w-18' : 'w-64'} ${navClassName}`}\n style={\n (!effectiveCollapsed && navWidth !== '16rem') || (effectiveCollapsed && navWidthCollapsed !== '4.5rem')\n ? ({\n width: effectiveCollapsed ? navWidthCollapsed : navWidth\n } as React.CSSProperties)\n : undefined\n }\n aria-label=\"Main navigation\"\n >\n {/* Nav Header with Toggle */}\n\n {/* Nav Content - Scrollable */}\n <nav\n ref={navRef}\n className=\"flex-1 overflow-y-auto overflow-x-hidden scrollbar-thin\"\n data-collapsed={effectiveCollapsed}\n onScroll={(e) => {\n scrollPosRef.current = (e.currentTarget as HTMLDivElement).scrollTop;\n }}\n >\n {showToggle && (\n <>\n <div className=\"py-2\">\n <LeftNavItem\n icon={effectiveCollapsed ? 'layout-sidebar-left-expand' : 'layout-sidebar-left-collapse'}\n iconSize=\"md\"\n onClick={handleToggleClick}\n disableActiveState\n title={effectiveCollapsed ? 'Expand sidebar' : 'Collapse sidebar'}\n >\n {header}\n </LeftNavItem>\n\n {/* Divider - Subtle separator between sections */}\n <div className=\"h-px bg-border mx-3 mt-1.5\" aria-hidden=\"true\" />\n </div>\n </>\n )}\n {nav}\n </nav>\n </aside>\n\n {/* Main Content Area */}\n <main\n ref={contentRef as React.RefObject<HTMLDivElement>}\n className={`flex-1 overflow-y-auto ${embedded ? 'h-60' : ''} ${contentClassName}`}\n >\n {children}\n </main>\n </div>\n );\n}\n\nLeftNavLayout.displayName = 'LeftNavLayout';\n\nexport default LeftNavLayout;\n"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"left-nav-section.d.ts","sourceRoot":"","sources":["../../../../src/components/layout/left-nav-layout/left-nav-section.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAA+B,MAAM,OAAO,CAAC;AAG/D,MAAM,MAAM,mBAAmB,GAAG;IAChC,yDAAyD;IACzD,QAAQ,EAAE,SAAS,CAAC;IACpB,+DAA+D;IAC/D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,8DAA8D;IAC9D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kDAAkD;IAClD,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,sEAAsE;IACtE,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,sFAAsF;IACtF,EAAE,CAAC,EAAE,MAAM,CAAC;CACb,CAAC;AAEF;;;;;;;;;;;;;;;;;;GAkBG;AACH,iBAAS,cAAc,CAAC,EACtB,QAAQ,EACR,KAAK,EACL,SAAc,EACd,WAAmB,EACnB,gBAAwB,EACxB,EAAE,EACH,EAAE,QAAQ,CAAC,mBAAmB,CAAC,2CAmI/B;kBA1IQ,cAAc;;;AA8IvB,eAAe,cAAc,CAAC"}
1
+ {"version":3,"file":"left-nav-section.d.ts","sourceRoot":"","sources":["../../../../src/components/layout/left-nav-layout/left-nav-section.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAA+B,MAAM,OAAO,CAAC;AAG/D,MAAM,MAAM,mBAAmB,GAAG;IAChC,yDAAyD;IACzD,QAAQ,EAAE,SAAS,CAAC;IACpB,+DAA+D;IAC/D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,8DAA8D;IAC9D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kDAAkD;IAClD,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,sEAAsE;IACtE,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,sFAAsF;IACtF,EAAE,CAAC,EAAE,MAAM,CAAC;CACb,CAAC;AAEF;;;;;;;;;;;;;;;;;;GAkBG;AACH,iBAAS,cAAc,CAAC,EACtB,QAAQ,EACR,KAAK,EACL,SAAc,EACd,WAAmB,EACnB,gBAAwB,EACxB,EAAE,EACH,EAAE,QAAQ,CAAC,mBAAmB,CAAC,2CAqI/B;kBA5IQ,cAAc;;;AAgJvB,eAAe,cAAc,CAAC"}
@@ -67,17 +67,16 @@ function LeftNavSection({
67
67
  }
68
68
  };
69
69
  const effectiveCollapsed = isNavCollapsed ? false : isCollapsed;
70
- return /* @__PURE__ */ jsxs("div", { ref: sectionRef, className: `${className}`, children: [
70
+ return /* @__PURE__ */ jsxs("div", { ref: sectionRef, className: `py-1 [&:last-child>*:last-child]:hidden ${className}`, children: [
71
71
  label && /* @__PURE__ */ jsxs(
72
72
  "div",
73
73
  {
74
74
  className: `
75
- px-2 py-1.5
76
- text-[9px] font-semibold uppercase tracking-wider
77
- text-[#FBFBFF]/40
78
- text-center leading-tight wrap-break-word
79
- flex flex-col items-center gap-0.5
80
- ${collapsible ? "cursor-pointer hover:text-[#FBFBFF] transition-colors" : ""}
75
+ px-3 mb-1.5 mt-1
76
+ text-xs font-semibold uppercase tracking-wider
77
+ text-muted-foreground
78
+ [nav[data-collapsed='true']_&]:hidden
79
+ ${collapsible ? "cursor-pointer hover:text-foreground transition-colors flex items-center justify-between gap-2" : ""}
81
80
  `,
82
81
  onClick: toggleCollapsed,
83
82
  role: collapsible ? "button" : void 0,
@@ -90,7 +89,7 @@ function LeftNavSection({
90
89
  }
91
90
  } : void 0,
92
91
  children: [
93
- /* @__PURE__ */ jsx("span", { className: "select-none", children: label }),
92
+ /* @__PURE__ */ jsx("span", { children: label }),
94
93
  collapsible && /* @__PURE__ */ jsx(
95
94
  Icon,
96
95
  {
@@ -106,10 +105,11 @@ function LeftNavSection({
106
105
  "div",
107
106
  {
108
107
  ref: contentRef,
109
- className: `overflow-hidden transition-all duration-200 ${effectiveCollapsed && collapsible ? "max-h-0 opacity-0" : "max-h-500 opacity-100"}`,
108
+ className: `space-y-0.5 overflow-hidden transition-all duration-200 ${effectiveCollapsed && collapsible ? "max-h-0 opacity-0" : "max-h-[2000px] opacity-100"}`,
110
109
  children
111
110
  }
112
- )
111
+ ),
112
+ /* @__PURE__ */ jsx("div", { className: "h-px bg-border mx-3 mt-1.5", "aria-hidden": "true" })
113
113
  ] });
114
114
  }
115
115
  LeftNavSection.displayName = "LeftNavSection";
@@ -1 +1 @@
1
- {"version":3,"file":"left-nav-section.js","sources":["../../../../src/components/layout/left-nav-layout/left-nav-section.tsx"],"sourcesContent":["import { ReactNode, useState, useRef, useEffect } from 'react';\nimport Icon from '../../system/icon/icon';\n\nexport type LeftNavSectionProps = {\n /** Section content (typically LeftNavItem components) */\n children: ReactNode;\n /** Optional section header label (hidden in collapsed mode) */\n label?: string;\n /** Additional CSS classes applied to the section container */\n className?: string;\n /** Enable collapsible behavior for the section */\n collapsible?: boolean;\n /** Default collapsed state (only applies when collapsible is true) */\n defaultCollapsed?: boolean;\n /** Unique identifier for localStorage persistence. If not provided, label is used. */\n id?: string;\n};\n\n/**\n * LeftNavSection - Section grouping for LeftNavLayout navigation items\n *\n * Groups related navigation items together with an optional label.\n * In collapsed mode, the label is hidden but the grouping is preserved.\n * Supports collapsible behavior with smooth animations and localStorage persistence.\n *\n * @example\n * ```tsx\n * <LeftNavSection label=\"Main\">\n * <LeftNavItem icon={<HomeIcon />} href=\"/\">Home</LeftNavItem>\n * <LeftNavItem icon={<DashboardIcon />} href=\"/dashboard\">Dashboard</LeftNavItem>\n * </LeftNavSection>\n *\n * <LeftNavSection label=\"Settings\" collapsible defaultCollapsed id=\"settings-section\">\n * <LeftNavItem icon={<SettingsIcon />} href=\"/settings\">Settings</LeftNavItem>\n * </LeftNavSection>\n * ```\n */\nfunction LeftNavSection({\n children,\n label,\n className = '',\n collapsible = false,\n defaultCollapsed = false,\n id\n}: Readonly<LeftNavSectionProps>) {\n const STORAGE_KEY = 'left-nav-sections';\n\n // Generate unique identifier from id or label\n const sectionId = id || label || null;\n\n // Helper to read all section states from localStorage\n const getSectionStates = (): Record<string, boolean> => {\n if (typeof window === 'undefined') return {};\n\n try {\n const stored = localStorage.getItem(STORAGE_KEY);\n return stored ? JSON.parse(stored) : {};\n } catch (error) {\n // eslint-disable-next-line no-console\n console.warn('Failed to read section states from localStorage:', error);\n return {};\n }\n };\n\n // Helper to save a section state to localStorage\n const saveSectionState = (sectionKey: string, collapsed: boolean) => {\n try {\n const states = getSectionStates();\n states[sectionKey] = collapsed;\n localStorage.setItem(STORAGE_KEY, JSON.stringify(states));\n } catch (error) {\n // eslint-disable-next-line no-console\n console.warn('Failed to save section state to localStorage:', error);\n }\n };\n\n // Initialize collapsed state from localStorage if collapsible\n const [isCollapsed, setIsCollapsed] = useState(() => {\n if (!collapsible || !sectionId) return defaultCollapsed;\n\n const states = getSectionStates();\n return sectionId in states ? states[sectionId] : defaultCollapsed;\n });\n\n const [isNavCollapsed, setIsNavCollapsed] = useState(false);\n const contentRef = useRef<HTMLDivElement>(null);\n const sectionRef = useRef<HTMLDivElement>(null);\n\n // Check if parent nav is collapsed (icon-only mode)\n useEffect(() => {\n const checkNavCollapsed = () => {\n const navElement = sectionRef.current?.closest('nav');\n if (navElement) {\n setIsNavCollapsed(navElement.getAttribute('data-collapsed') === 'true');\n }\n };\n\n checkNavCollapsed();\n\n const navElement = sectionRef.current?.closest('nav');\n if (navElement) {\n const observer = new MutationObserver(checkNavCollapsed);\n observer.observe(navElement, {\n attributes: true,\n attributeFilter: ['data-collapsed']\n });\n return () => observer.disconnect();\n }\n\n return undefined;\n }, []);\n\n const toggleCollapsed = () => {\n if (collapsible) {\n const newState = !isCollapsed;\n setIsCollapsed(newState);\n\n // Persist to localStorage\n if (sectionId) {\n saveSectionState(sectionId, newState);\n }\n }\n };\n\n // Auto-expand when nav is in icon-only mode\n const effectiveCollapsed = isNavCollapsed ? false : isCollapsed;\n\n return (\n <div ref={sectionRef} className={`${className}`}>\n {/* Section Label - Hidden in collapsed mode */}\n {label && (\n <div\n className={`\n px-2 py-1.5\n text-[9px] font-semibold uppercase tracking-wider\n text-[#FBFBFF]/40\n text-center leading-tight wrap-break-word\n flex flex-col items-center gap-0.5\n ${collapsible ? 'cursor-pointer hover:text-[#FBFBFF] transition-colors' : ''}\n `}\n onClick={toggleCollapsed}\n role={collapsible ? 'button' : undefined}\n aria-expanded={collapsible ? !effectiveCollapsed : undefined}\n tabIndex={collapsible ? 0 : undefined}\n onKeyDown={\n collapsible\n ? (e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n toggleCollapsed();\n }\n }\n : undefined\n }\n >\n <span className=\"select-none\">{label}</span>\n {collapsible && (\n <Icon\n name=\"chevron-down\"\n size=\"xs\"\n className={`transition-transform duration-200 ${effectiveCollapsed ? '-rotate-90' : ''}`}\n />\n )}\n </div>\n )}\n\n {/* Section Items */}\n <div\n ref={contentRef}\n className={`overflow-hidden transition-all duration-200 ${effectiveCollapsed && collapsible ? 'max-h-0 opacity-0' : 'max-h-500 opacity-100'}`}\n >\n {children}\n </div>\n </div>\n );\n}\n\nLeftNavSection.displayName = 'LeftNavSection';\n\nexport default LeftNavSection;\n"],"names":["navElement"],"mappings":"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"}
1
+ {"version":3,"file":"left-nav-section.js","sources":["../../../../src/components/layout/left-nav-layout/left-nav-section.tsx"],"sourcesContent":["import { ReactNode, useState, useRef, useEffect } from 'react';\nimport Icon from '../../system/icon/icon';\n\nexport type LeftNavSectionProps = {\n /** Section content (typically LeftNavItem components) */\n children: ReactNode;\n /** Optional section header label (hidden in collapsed mode) */\n label?: string;\n /** Additional CSS classes applied to the section container */\n className?: string;\n /** Enable collapsible behavior for the section */\n collapsible?: boolean;\n /** Default collapsed state (only applies when collapsible is true) */\n defaultCollapsed?: boolean;\n /** Unique identifier for localStorage persistence. If not provided, label is used. */\n id?: string;\n};\n\n/**\n * LeftNavSection - Section grouping for LeftNavLayout navigation items\n *\n * Groups related navigation items together with an optional label.\n * In collapsed mode, the label is hidden but the grouping is preserved.\n * Supports collapsible behavior with smooth animations and localStorage persistence.\n *\n * @example\n * ```tsx\n * <LeftNavSection label=\"Main\">\n * <LeftNavItem icon={<HomeIcon />} href=\"/\">Home</LeftNavItem>\n * <LeftNavItem icon={<DashboardIcon />} href=\"/dashboard\">Dashboard</LeftNavItem>\n * </LeftNavSection>\n *\n * <LeftNavSection label=\"Settings\" collapsible defaultCollapsed id=\"settings-section\">\n * <LeftNavItem icon={<SettingsIcon />} href=\"/settings\">Settings</LeftNavItem>\n * </LeftNavSection>\n * ```\n */\nfunction LeftNavSection({\n children,\n label,\n className = '',\n collapsible = false,\n defaultCollapsed = false,\n id\n}: Readonly<LeftNavSectionProps>) {\n const STORAGE_KEY = 'left-nav-sections';\n\n // Generate unique identifier from id or label\n const sectionId = id || label || null;\n\n // Helper to read all section states from localStorage\n const getSectionStates = (): Record<string, boolean> => {\n if (typeof window === 'undefined') return {};\n\n try {\n const stored = localStorage.getItem(STORAGE_KEY);\n return stored ? JSON.parse(stored) : {};\n } catch (error) {\n // eslint-disable-next-line no-console\n console.warn('Failed to read section states from localStorage:', error);\n return {};\n }\n };\n\n // Helper to save a section state to localStorage\n const saveSectionState = (sectionKey: string, collapsed: boolean) => {\n try {\n const states = getSectionStates();\n states[sectionKey] = collapsed;\n localStorage.setItem(STORAGE_KEY, JSON.stringify(states));\n } catch (error) {\n // eslint-disable-next-line no-console\n console.warn('Failed to save section state to localStorage:', error);\n }\n };\n\n // Initialize collapsed state from localStorage if collapsible\n const [isCollapsed, setIsCollapsed] = useState(() => {\n if (!collapsible || !sectionId) return defaultCollapsed;\n\n const states = getSectionStates();\n return sectionId in states ? states[sectionId] : defaultCollapsed;\n });\n\n const [isNavCollapsed, setIsNavCollapsed] = useState(false);\n const contentRef = useRef<HTMLDivElement>(null);\n const sectionRef = useRef<HTMLDivElement>(null);\n\n // Check if parent nav is collapsed (icon-only mode)\n useEffect(() => {\n const checkNavCollapsed = () => {\n const navElement = sectionRef.current?.closest('nav');\n if (navElement) {\n setIsNavCollapsed(navElement.getAttribute('data-collapsed') === 'true');\n }\n };\n\n checkNavCollapsed();\n\n const navElement = sectionRef.current?.closest('nav');\n if (navElement) {\n const observer = new MutationObserver(checkNavCollapsed);\n observer.observe(navElement, {\n attributes: true,\n attributeFilter: ['data-collapsed']\n });\n return () => observer.disconnect();\n }\n\n return undefined;\n }, []);\n\n const toggleCollapsed = () => {\n if (collapsible) {\n const newState = !isCollapsed;\n setIsCollapsed(newState);\n\n // Persist to localStorage\n if (sectionId) {\n saveSectionState(sectionId, newState);\n }\n }\n };\n\n // Auto-expand when nav is in icon-only mode\n const effectiveCollapsed = isNavCollapsed ? false : isCollapsed;\n\n return (\n <div ref={sectionRef} className={`py-1 [&:last-child>*:last-child]:hidden ${className}`}>\n {/* Section Label - Hidden in collapsed mode */}\n {label && (\n <div\n className={`\n px-3 mb-1.5 mt-1\n text-xs font-semibold uppercase tracking-wider\n text-muted-foreground\n [nav[data-collapsed='true']_&]:hidden\n ${collapsible ? 'cursor-pointer hover:text-foreground transition-colors flex items-center justify-between gap-2' : ''}\n `}\n onClick={toggleCollapsed}\n role={collapsible ? 'button' : undefined}\n aria-expanded={collapsible ? !effectiveCollapsed : undefined}\n tabIndex={collapsible ? 0 : undefined}\n onKeyDown={\n collapsible\n ? (e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n toggleCollapsed();\n }\n }\n : undefined\n }\n >\n <span>{label}</span>\n {collapsible && (\n <Icon\n name=\"chevron-down\"\n size=\"xs\"\n className={`transition-transform duration-200 ${effectiveCollapsed ? '-rotate-90' : ''}`}\n />\n )}\n </div>\n )}\n\n {/* Section Items */}\n <div\n ref={contentRef}\n className={`space-y-0.5 overflow-hidden transition-all duration-200 ${effectiveCollapsed && collapsible ? 'max-h-0 opacity-0' : 'max-h-[2000px] opacity-100'}`}\n >\n {children}\n </div>\n\n {/* Divider - Subtle separator between sections (hidden on last section) */}\n <div className=\"h-px bg-border mx-3 mt-1.5\" aria-hidden=\"true\" />\n </div>\n );\n}\n\nLeftNavSection.displayName = 'LeftNavSection';\n\nexport default LeftNavSection;\n"],"names":["navElement"],"mappings":"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"}
@@ -2,8 +2,8 @@ import { jsxs, Fragment, jsx } from "react/jsx-runtime";
2
2
  import { useState, useRef, useCallback, useEffect, useLayoutEffect, useContext, createContext } from "react";
3
3
  import { createPortal } from "react-dom";
4
4
  import Button from "../../forms/button/button.js";
5
- import { Icon } from "../../system/icon/icon.js";
6
5
  import { gapSizes } from "../../../theme/size-tokens.js";
6
+ import { Icon } from "../../system/icon/icon.js";
7
7
  const DropdownContext = createContext(null);
8
8
  function Dropdown({
9
9
  trigger,
@@ -23,8 +23,8 @@ function Navbar({
23
23
  "nav",
24
24
  {
25
25
  "data-appearance": appearance,
26
- className: `${sticky ? "sticky top-0 z-50" : ""} ${appearanceClasses[appearance]} ${borderClasses[border]} h-14 md:h-16 ${className}`,
27
- children: /* @__PURE__ */ jsx("div", { className: "w-auto max-w-full mx-4 h-full", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between h-full px-3 md:px-0", children: [
26
+ className: `${sticky ? "sticky top-0 z-50" : ""} ${appearanceClasses[appearance]} ${borderClasses[border]} ${className}`,
27
+ children: /* @__PURE__ */ jsx("div", { className: "w-auto max-w-full mx-4", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between h-14 md:h-16 px-3 md:px-0", children: [
28
28
  brand && /* @__PURE__ */ jsx("div", { className: "shrink-0", children: brand }),
29
29
  /* @__PURE__ */ jsx("div", { className: "hidden md:flex md:items-center md:space-x-6 md:flex-1 md:ml-10", children }),
30
30
  actions && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1", children: actions })
@@ -1 +1 @@
1
- {"version":3,"file":"navbar.js","sources":["../../../../src/components/navigation/navbar/navbar.tsx"],"sourcesContent":["import { ReactNode } from 'react';\n\nexport type NavbarProps = {\n /** Brand logo or text to display on the left side */\n brand?: ReactNode;\n /** Navigation links or items to display in the center */\n children: ReactNode;\n /** Enable sticky positioning at the top of viewport */\n sticky?: boolean;\n /** Additional CSS classes for the navbar container */\n className?: string;\n /** Action buttons or elements to display on the right side */\n actions?: ReactNode;\n /** Visual style variant for the navbar background */\n appearance?: 'solid' | 'blur' | 'transparent';\n /** Border configuration for top and/or bottom edges */\n border?: 'none' | 'bottom' | 'top' | 'both';\n};\n\n/**\n * Navbar Component - Responsive navigation\n * - Sticky positioning option\n * - Brand logo section\n * - Action buttons area\n * - Fully responsive\n * - Configurable container size\n * - Appearance modes: solid, blur (frosted glass), transparent\n * - Configurable borders: none, bottom, top, or both\n */\nfunction Navbar({\n brand,\n children,\n sticky = true,\n className = '',\n actions,\n appearance = 'solid',\n border = 'none'\n}: Readonly<NavbarProps>) {\n // Appearance styles\n const appearanceClasses = {\n solid: 'bg-background shadow-sm',\n blur: 'bg-background/70 backdrop-blur-md supports-[backdrop-filter]:bg-background/60 border border-border/60',\n transparent: 'bg-transparent'\n } as const;\n\n const borderClasses = {\n none: '',\n bottom: 'border-b border-border',\n top: 'border-t border-border',\n both: 'border-y border-border'\n };\n\n return (\n <nav\n data-appearance={appearance}\n className={`${sticky ? 'sticky top-0 z-50' : ''} ${appearanceClasses[appearance]} ${borderClasses[border]} h-14 md:h-16 ${className}`}\n >\n <div className=\"w-auto max-w-full mx-4 h-full\">\n <div className=\"flex items-center justify-between h-full px-3 md:px-0\">\n {/* Brand */}\n {brand && <div className=\"shrink-0\">{brand}</div>}\n\n {/* Navigation */}\n <div className=\"hidden md:flex md:items-center md:space-x-6 md:flex-1 md:ml-10\">{children}</div>\n\n {/* Actions */}\n {actions && <div className=\"flex items-center gap-1\">{actions}</div>}\n </div>\n </div>\n </nav>\n );\n}\n\nNavbar.displayName = 'Navbar';\n\nexport default Navbar;\n"],"names":[],"mappings":";AA6BA,SAAS,OAAO;AAAA,EACd;AAAA,EACA;AAAA,EACA,SAAS;AAAA,EACT,YAAY;AAAA,EACZ;AAAA,EACA,aAAa;AAAA,EACb,SAAS;AACX,GAA0B;AAExB,QAAM,oBAAoB;AAAA,IACxB,OAAO;AAAA,IACP,MAAM;AAAA,IACN,aAAa;AAAA,EAAA;AAGf,QAAM,gBAAgB;AAAA,IACpB,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,KAAK;AAAA,IACL,MAAM;AAAA,EAAA;AAGR,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,mBAAiB;AAAA,MACjB,WAAW,GAAG,SAAS,sBAAsB,EAAE,IAAI,kBAAkB,UAAU,CAAC,IAAI,cAAc,MAAM,CAAC,iBAAiB,SAAS;AAAA,MAEnI,8BAAC,OAAA,EAAI,WAAU,iCACb,UAAA,qBAAC,OAAA,EAAI,WAAU,yDAEZ,UAAA;AAAA,QAAA,SAAS,oBAAC,OAAA,EAAI,WAAU,YAAY,UAAA,OAAM;AAAA,QAG3C,oBAAC,OAAA,EAAI,WAAU,kEAAkE,SAAA,CAAS;AAAA,QAGzF,WAAW,oBAAC,OAAA,EAAI,WAAU,2BAA2B,UAAA,QAAA,CAAQ;AAAA,MAAA,EAAA,CAChE,EAAA,CACF;AAAA,IAAA;AAAA,EAAA;AAGN;AAEA,OAAO,cAAc;"}
1
+ {"version":3,"file":"navbar.js","sources":["../../../../src/components/navigation/navbar/navbar.tsx"],"sourcesContent":["import { ReactNode } from 'react';\n\nexport type NavbarProps = {\n /** Brand logo or text to display on the left side */\n brand?: ReactNode;\n /** Navigation links or items to display in the center */\n children: ReactNode;\n /** Enable sticky positioning at the top of viewport */\n sticky?: boolean;\n /** Additional CSS classes for the navbar container */\n className?: string;\n /** Action buttons or elements to display on the right side */\n actions?: ReactNode;\n /** Visual style variant for the navbar background */\n appearance?: 'solid' | 'blur' | 'transparent';\n /** Border configuration for top and/or bottom edges */\n border?: 'none' | 'bottom' | 'top' | 'both';\n};\n\n/**\n * Navbar Component - Responsive navigation\n * - Sticky positioning option\n * - Brand logo section\n * - Action buttons area\n * - Fully responsive\n * - Configurable container size\n * - Appearance modes: solid, blur (frosted glass), transparent\n * - Configurable borders: none, bottom, top, or both\n */\nfunction Navbar({\n brand,\n children,\n sticky = true,\n className = '',\n actions,\n appearance = 'solid',\n border = 'none'\n}: Readonly<NavbarProps>) {\n // Appearance styles\n const appearanceClasses = {\n solid: 'bg-background shadow-sm',\n blur: 'bg-background/70 backdrop-blur-md supports-[backdrop-filter]:bg-background/60 border border-border/60',\n transparent: 'bg-transparent'\n } as const;\n\n const borderClasses = {\n none: '',\n bottom: 'border-b border-border',\n top: 'border-t border-border',\n both: 'border-y border-border'\n };\n\n return (\n <nav\n data-appearance={appearance}\n className={`${sticky ? 'sticky top-0 z-50' : ''} ${appearanceClasses[appearance]} ${borderClasses[border]} ${className}`}\n >\n <div className=\"w-auto max-w-full mx-4\">\n <div className=\"flex items-center justify-between h-14 md:h-16 px-3 md:px-0\">\n {/* Brand */}\n {brand && <div className=\"shrink-0\">{brand}</div>}\n\n {/* Navigation */}\n <div className=\"hidden md:flex md:items-center md:space-x-6 md:flex-1 md:ml-10\">{children}</div>\n\n {/* Actions */}\n {actions && <div className=\"flex items-center gap-1\">{actions}</div>}\n </div>\n </div>\n </nav>\n );\n}\n\nNavbar.displayName = 'Navbar';\n\nexport default Navbar;\n"],"names":[],"mappings":";AA6BA,SAAS,OAAO;AAAA,EACd;AAAA,EACA;AAAA,EACA,SAAS;AAAA,EACT,YAAY;AAAA,EACZ;AAAA,EACA,aAAa;AAAA,EACb,SAAS;AACX,GAA0B;AAExB,QAAM,oBAAoB;AAAA,IACxB,OAAO;AAAA,IACP,MAAM;AAAA,IACN,aAAa;AAAA,EAAA;AAGf,QAAM,gBAAgB;AAAA,IACpB,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,KAAK;AAAA,IACL,MAAM;AAAA,EAAA;AAGR,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,mBAAiB;AAAA,MACjB,WAAW,GAAG,SAAS,sBAAsB,EAAE,IAAI,kBAAkB,UAAU,CAAC,IAAI,cAAc,MAAM,CAAC,IAAI,SAAS;AAAA,MAEtH,8BAAC,OAAA,EAAI,WAAU,0BACb,UAAA,qBAAC,OAAA,EAAI,WAAU,+DAEZ,UAAA;AAAA,QAAA,SAAS,oBAAC,OAAA,EAAI,WAAU,YAAY,UAAA,OAAM;AAAA,QAG3C,oBAAC,OAAA,EAAI,WAAU,kEAAkE,SAAA,CAAS;AAAA,QAGzF,WAAW,oBAAC,OAAA,EAAI,WAAU,2BAA2B,UAAA,QAAA,CAAQ;AAAA,MAAA,EAAA,CAChE,EAAA,CACF;AAAA,IAAA;AAAA,EAAA;AAGN;AAEA,OAAO,cAAc;"}