@orchard9ai/design-system
Version:
DaisyUI-based component library for Orchard9 applications
1 lines • 330 kB
Source Map (JSON)
{"version":3,"sources":["../src/components/Typography/Heading.tsx","../src/utils/cn.ts","../src/components/Typography/Text.tsx","../src/components/Typography/Prose.tsx","../src/components/Typography/Link.tsx","../src/components/Typography/Code.tsx","../src/components/Typography/List.tsx","../src/components/Logo/Logo.tsx","../src/components/Error/ErrorBoundary.tsx","../src/components/Error/ErrorPage.tsx","../src/components/Button/Button.tsx","../src/components/Error/ErrorMessage.tsx","../src/components/Button/ButtonGroup.tsx","../src/theme/ThemeProvider.tsx","../src/components/Loading/LoadingButton.tsx","../src/components/Loading/LoadingContainer.tsx","../src/components/Loading/LoadingSkeleton.tsx","../src/hooks/useAsyncOperation.ts","../src/utils/verify-imports.ts","../src/components/FormControl.tsx","../src/components/Input.tsx","../src/components/Select.tsx","../src/components/Textarea.tsx","../src/components/Checkbox.tsx","../src/components/Radio.tsx","../src/components/Toggle.tsx","../src/components/Layout/Box.tsx","../src/components/Layout/Flex.tsx","../src/components/Layout/Spacer.tsx","../src/components/Card.tsx","../src/components/Container.tsx","../src/components/Stack.tsx","../src/components/Grid.tsx","../src/components/Drawer.tsx","../src/components/Hero.tsx","../src/components/Alert.tsx","../src/components/Toast/ToastProvider.tsx","../src/components/Modal.tsx","../src/components/Progress.tsx","../src/components/Badge.tsx","../src/components/Skeleton.tsx","../src/components/Dropdown.tsx","../src/components/Tooltip.tsx","../src/components/Table/Table.tsx","../src/components/Stat/Stat.tsx","../src/components/Avatar/Avatar.tsx","../src/components/Timeline/Timeline.tsx","../src/components/Pagination/Pagination.tsx","../src/components/EmptyState/EmptyState.tsx","../src/components/Breadcrumb/Breadcrumb.tsx","../src/components/Tabs/Tabs.tsx","../src/components/Accordion/Accordion.tsx","../src/components/VerticalScroller/VerticalScroller.core.ts","../src/components/VerticalScroller/ScrollAnimation.ts","../src/components/VerticalScroller/VerticalScroller.tsx","../src/components/VerticalScroller/useVerticalScroller.ts","../src/components/Icons/SocialIcons.tsx","../src/components/FloatingActionButton/FloatingActionButton.tsx","../src/theme/useThemeColors.ts","../src/theme/ThemePreview.tsx","../src/themes/index.ts","../src/tokens/hooks.ts","../src/tokens/tokens.json","../src/tokens/constants.ts","../src/hooks/useMediaQuery.ts","../src/layout/ThreeColumnLayout.tsx","../src/layout/AuthLayout.tsx","../src/layout/Icons.tsx","../src/layout/MobileHeader.tsx","../src/layout/SlideOutDrawer.tsx","../src/layout/LayoutSidebar.tsx","../src/layout/NavigationItem.tsx","../src/layout/SidebarSection.tsx","../src/layout/ThemeSwitcher.tsx","../src/layout/FooterLinks.tsx","../src/layout/CenterPage.tsx"],"sourcesContent":["import * as React from 'react';\nimport { cn } from '../../utils/cn';\n\ntype HeadingLevel = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';\ntype HeadingSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | '4xl' | '5xl';\ntype HeadingWeight = 'normal' | 'medium' | 'semibold' | 'bold' | 'extrabold';\ntype HeadingColor = 'default' | 'primary' | 'secondary' | 'muted' | 'error';\ntype HeadingAlign = 'left' | 'center' | 'right' | 'justify';\n\nexport interface HeadingProps {\n as?: HeadingLevel;\n size?: HeadingSize;\n weight?: HeadingWeight;\n color?: HeadingColor;\n align?: HeadingAlign;\n truncate?: boolean;\n clamp?: number;\n gradient?: boolean;\n id?: string;\n children: React.ReactNode;\n className?: string;\n}\n\nconst sizeClasses: Record<HeadingSize, string> = {\n xs: 'text-xs',\n sm: 'text-sm',\n md: 'text-base md:text-lg',\n lg: 'text-lg md:text-xl lg:text-2xl',\n xl: 'text-xl md:text-2xl lg:text-3xl',\n '2xl': 'text-2xl md:text-3xl lg:text-4xl',\n '3xl': 'text-3xl md:text-4xl lg:text-5xl',\n '4xl': 'text-4xl md:text-5xl lg:text-6xl',\n '5xl': 'text-5xl md:text-6xl lg:text-7xl',\n};\n\nconst headingSizeMap: Record<\n HeadingLevel,\n { default: HeadingSize; md: HeadingSize; lg: HeadingSize }\n> = {\n h1: { default: 'xl', md: '2xl', lg: '2xl' },\n h2: { default: 'lg', md: 'xl', lg: 'xl' },\n h3: { default: 'md', md: 'lg', lg: 'lg' },\n h4: { default: 'sm', md: 'md', lg: 'md' },\n h5: { default: 'xs', md: 'sm', lg: 'sm' },\n h6: { default: 'xs', md: 'xs', lg: 'xs' },\n};\n\nconst weightClasses: Record<HeadingWeight, string> = {\n normal: 'font-normal',\n medium: 'font-medium',\n semibold: 'font-semibold',\n bold: 'font-bold',\n extrabold: 'font-extrabold',\n};\n\nconst colorClasses: Record<HeadingColor, string> = {\n default: 'text-base-content',\n primary: 'text-primary',\n secondary: 'text-secondary',\n muted: 'text-base-content/70',\n error: 'text-error',\n};\n\nconst alignClasses: Record<HeadingAlign, string> = {\n left: 'text-left',\n center: 'text-center',\n right: 'text-right',\n justify: 'text-justify',\n};\n\nexport const Heading = React.forwardRef<HTMLHeadingElement, HeadingProps>(\n (\n {\n as: Component = 'h2',\n size,\n weight = 'bold',\n color = 'default',\n align,\n truncate = false,\n clamp,\n gradient = false,\n id,\n children,\n className,\n },\n ref\n ) => {\n // Use automatic sizing based on heading level if size not provided\n const autoSize = size || sizeClasses[headingSizeMap[Component].default];\n const sizeClass = size ? sizeClasses[size] : autoSize;\n\n const clampClass = clamp ? `line-clamp-${clamp}` : truncate ? 'truncate' : '';\n\n const gradientClass = gradient\n ? 'bg-gradient-to-r from-primary to-secondary bg-clip-text text-transparent'\n : '';\n\n return (\n <Component\n ref={ref}\n id={id}\n className={cn(\n sizeClass,\n weightClasses[weight],\n !gradient && colorClasses[color],\n align && alignClasses[align],\n clampClass,\n gradientClass,\n 'tracking-tight',\n className\n )}\n >\n {children}\n </Component>\n );\n }\n);\n\nHeading.displayName = 'Heading';\n","import { clsx, type ClassValue } from 'clsx';\n\n/**\n * Combines class names with intelligent conditional class handling.\n *\n * This utility uses clsx to handle conditional classes, making it easy to\n * apply dynamic styling based on component state. Perfect for use with\n * Tailwind CSS and DaisyUI classes.\n *\n * @example\n * // Basic usage\n * cn('px-4 py-2', 'text-white', 'bg-blue-500')\n * // => 'px-4 py-2 text-white bg-blue-500'\n *\n * @example\n * // Conditional classes\n * cn('btn', isLoading && 'loading', isDisabled && 'btn-disabled')\n *\n * @example\n * // Object syntax\n * cn('base', {\n * 'bg-primary': isPrimary,\n * 'bg-secondary': !isPrimary,\n * })\n *\n * @example\n * // Array syntax\n * cn(['btn', variant && `btn-${variant}`])\n *\n * @example\n * // With DaisyUI components\n * <button className={cn('btn', size && `btn-${size}`, className)}>\n * Click me\n * </button>\n *\n * @example\n * // Common patterns\n * cn(\n * 'base-class', // Always applied\n * condition && 'class-1', // Conditionally applied\n * {\n * 'class-2': bool1, // Object syntax\n * 'class-3': bool2,\n * },\n * className // Props pass-through\n * )\n *\n * @param inputs - Class names, conditionals, arrays, or objects to merge\n * @returns Merged class string with falsy values filtered out\n */\nexport function cn(...inputs: ClassValue[]): string {\n return clsx(inputs);\n}\n","import * as React from 'react';\nimport { cn } from '../../utils/cn';\n\ntype TextElement = 'p' | 'span' | 'div' | 'label';\ntype TextSize = 'xs' | 'sm' | 'base' | 'lg' | 'xl' | '2xl';\ntype TextWeight = 'normal' | 'medium' | 'semibold' | 'bold';\ntype TextColor = 'default' | 'primary' | 'secondary' | 'muted' | 'error' | 'success';\ntype TextAlign = 'left' | 'center' | 'right' | 'justify';\ntype TextVariant = 'body' | 'caption' | 'overline' | 'helper' | 'error';\n\nexport interface TextProps {\n as?: TextElement;\n size?: TextSize;\n weight?: TextWeight;\n color?: TextColor;\n align?: TextAlign;\n italic?: boolean;\n underline?: boolean;\n strikethrough?: boolean;\n uppercase?: boolean;\n lowercase?: boolean;\n capitalize?: boolean;\n truncate?: boolean;\n clamp?: number;\n nowrap?: boolean;\n variant?: TextVariant;\n children: React.ReactNode;\n className?: string;\n}\n\nconst sizeClasses: Record<TextSize, string> = {\n xs: 'text-xs',\n sm: 'text-sm',\n base: 'text-base',\n lg: 'text-lg',\n xl: 'text-xl',\n '2xl': 'text-2xl',\n};\n\nconst weightClasses: Record<TextWeight, string> = {\n normal: 'font-normal',\n medium: 'font-medium',\n semibold: 'font-semibold',\n bold: 'font-bold',\n};\n\nconst colorClasses: Record<TextColor, string> = {\n default: 'text-base-content',\n primary: 'text-primary',\n secondary: 'text-secondary',\n muted: 'text-base-content/70',\n error: 'text-error',\n success: 'text-success',\n};\n\nconst alignClasses: Record<TextAlign, string> = {\n left: 'text-left',\n center: 'text-center',\n right: 'text-right',\n justify: 'text-justify',\n};\n\nconst variantPresets: Record<TextVariant, Partial<TextProps>> = {\n body: { size: 'base', weight: 'normal' },\n caption: { size: 'sm', color: 'muted' },\n overline: { size: 'xs', weight: 'semibold', uppercase: true },\n helper: { size: 'sm', color: 'muted', italic: true },\n error: { size: 'sm', color: 'error', weight: 'medium' },\n};\n\nexport const Text = React.forwardRef<HTMLElement, TextProps>(\n (\n {\n as: Component = 'p',\n size,\n weight,\n color,\n align = 'left',\n italic = false,\n underline = false,\n strikethrough = false,\n uppercase = false,\n lowercase = false,\n capitalize = false,\n truncate = false,\n clamp,\n nowrap = false,\n variant,\n children,\n className,\n },\n ref\n ) => {\n // Apply variant presets if specified\n const variantProps = variant ? variantPresets[variant] : {};\n const finalSize = size || variantProps.size || 'base';\n const finalWeight = weight || variantProps.weight || 'normal';\n const finalColor = color || variantProps.color || 'default';\n const finalItalic = italic || variantProps.italic || false;\n const finalUppercase = uppercase || variantProps.uppercase || false;\n\n const textTransformClass =\n uppercase || finalUppercase\n ? 'uppercase'\n : lowercase\n ? 'lowercase'\n : capitalize\n ? 'capitalize'\n : '';\n\n const decorationClass = underline ? 'underline' : strikethrough ? 'line-through' : '';\n\n const clampClass = clamp ? `line-clamp-${clamp}` : truncate ? 'truncate' : '';\n\n return (\n <Component\n ref={ref as any}\n className={cn(\n sizeClasses[finalSize],\n weightClasses[finalWeight],\n colorClasses[finalColor],\n alignClasses[align],\n finalItalic && 'italic',\n decorationClass,\n textTransformClass,\n clampClass,\n nowrap && 'whitespace-nowrap',\n 'leading-relaxed',\n className\n )}\n >\n {children}\n </Component>\n );\n }\n);\n\nText.displayName = 'Text';\n","import * as React from 'react';\nimport { cn } from '../../utils/cn';\n\ntype ProseSize = 'sm' | 'base' | 'lg' | 'xl';\ntype ProseMaxWidth = 'none' | 'sm' | 'md' | 'lg' | 'xl' | '2xl';\n\nexport interface ProseProps {\n children: React.ReactNode;\n size?: ProseSize;\n maxWidth?: ProseMaxWidth;\n centered?: boolean;\n serif?: boolean;\n dropCap?: boolean;\n balancedText?: boolean;\n className?: string;\n}\n\nconst sizeClasses: Record<ProseSize, string> = {\n sm: 'prose-sm',\n base: 'prose',\n lg: 'prose-lg',\n xl: 'prose-xl',\n};\n\nconst maxWidthClasses: Record<ProseMaxWidth, string> = {\n none: 'max-w-none',\n sm: 'max-w-prose-sm',\n md: 'max-w-prose',\n lg: 'max-w-prose-lg',\n xl: 'max-w-prose-xl',\n '2xl': 'max-w-prose-2xl',\n};\n\nexport const Prose = React.forwardRef<HTMLDivElement, ProseProps>(\n (\n {\n children,\n size = 'base',\n maxWidth = 'lg',\n centered = false,\n serif = false,\n dropCap = false,\n balancedText = false,\n className,\n },\n ref\n ) => {\n return (\n <div\n ref={ref}\n className={cn(\n 'prose',\n sizeClasses[size],\n maxWidthClasses[maxWidth],\n centered && 'mx-auto',\n serif && 'font-serif',\n balancedText && '[text-wrap:balance]',\n // Dark mode support\n 'prose-headings:text-base-content',\n 'prose-p:text-base-content',\n 'prose-strong:text-base-content',\n 'prose-em:text-base-content',\n 'prose-blockquote:text-base-content/80',\n 'prose-lead:text-base-content',\n 'prose-a:text-primary',\n 'prose-a:no-underline',\n 'hover:prose-a:underline',\n 'prose-code:text-base-content',\n 'prose-code:bg-base-200',\n 'prose-code:px-1',\n 'prose-code:py-0.5',\n 'prose-code:rounded',\n 'prose-pre:bg-base-200',\n 'prose-pre:text-base-content',\n 'prose-ol:text-base-content',\n 'prose-ul:text-base-content',\n 'prose-li:text-base-content',\n 'prose-table:text-base-content',\n 'prose-thead:border-base-300',\n 'prose-tr:border-base-300',\n 'prose-th:text-base-content',\n 'prose-td:text-base-content',\n 'prose-hr:border-base-300',\n 'prose-figure:text-base-content',\n 'prose-figcaption:text-base-content/70',\n 'prose-video:rounded',\n 'prose-img:rounded',\n // First letter drop cap\n dropCap &&\n 'prose-p:first-of-type:first-letter:text-7xl prose-p:first-of-type:first-letter:font-bold prose-p:first-of-type:first-letter:float-left prose-p:first-of-type:first-letter:mr-3 prose-p:first-of-type:first-letter:mt-1 prose-p:first-of-type:first-letter:text-primary',\n className\n )}\n >\n {children}\n </div>\n );\n }\n);\n\nProse.displayName = 'Prose';\n","import * as React from 'react';\nimport { cn } from '../../utils/cn';\n\ntype LinkVariant = 'default' | 'primary' | 'muted' | 'nav';\ntype LinkUnderline = 'always' | 'hover' | 'none';\ntype LinkWeight = 'normal' | 'medium' | 'semibold' | 'bold';\n\nexport interface LinkProps {\n href?: string;\n to?: string; // For router integration\n variant?: LinkVariant;\n external?: boolean;\n download?: boolean | string;\n underline?: LinkUnderline;\n weight?: LinkWeight;\n icon?: React.ReactNode;\n iconPosition?: 'left' | 'right';\n children: React.ReactNode;\n className?: string;\n onClick?: (e: React.MouseEvent<HTMLAnchorElement>) => void;\n}\n\nconst variantClasses: Record<LinkVariant, string> = {\n default: 'text-primary hover:text-primary-focus',\n primary: 'text-primary hover:text-primary-focus',\n muted: 'text-base-content/70 hover:text-base-content',\n nav: 'text-base-content hover:text-primary transition-colors focus:!ring-offset-0',\n};\n\nconst underlineClasses: Record<LinkUnderline, string> = {\n always: 'underline',\n hover: 'no-underline hover:underline',\n none: 'no-underline',\n};\n\nconst weightClasses: Record<LinkWeight, string> = {\n normal: 'font-normal',\n medium: 'font-medium',\n semibold: 'font-semibold',\n bold: 'font-bold',\n};\n\nexport const Link = React.forwardRef<HTMLAnchorElement, LinkProps>(\n (\n {\n href,\n to,\n variant = 'default',\n external = false,\n download,\n underline = 'hover',\n weight = 'normal',\n icon,\n iconPosition = 'right',\n children,\n className,\n onClick,\n },\n ref\n ) => {\n const linkHref = href || to || '#';\n const isExternal = external || (typeof linkHref === 'string' && linkHref.startsWith('http'));\n\n const externalProps = isExternal\n ? {\n target: '_blank',\n rel: 'noopener noreferrer',\n }\n : {};\n\n const downloadProps = download\n ? {\n download: typeof download === 'string' ? download : true,\n }\n : {};\n\n const iconElement = icon && (\n <span className={cn('inline-flex items-center', iconPosition === 'left' ? 'mr-1' : 'ml-1')}>\n {icon}\n </span>\n );\n\n return (\n <a\n ref={ref}\n href={linkHref}\n className={cn(\n variant === 'nav'\n ? 'flex items-center focus-ring'\n : 'inline-flex items-center focus-ring',\n variantClasses[variant],\n underlineClasses[underline],\n weightClasses[weight],\n 'transition-colors duration-200',\n 'focus:!outline-none focus:!ring-1 focus:!ring-primary focus:!ring-offset-1',\n className\n )}\n onClick={onClick}\n {...externalProps}\n {...downloadProps}\n >\n {iconPosition === 'left' && iconElement}\n {children}\n {iconPosition === 'right' && iconElement}\n </a>\n );\n }\n);\n\nLink.displayName = 'Link';\n","import * as React from 'react';\nimport { cn } from '../../utils/cn';\n\ntype CodeTheme = 'light' | 'dark' | 'auto';\n\nexport interface CodeProps {\n children: string;\n language?: string;\n inline?: boolean;\n showLineNumbers?: boolean;\n highlightLines?: number[];\n copyButton?: boolean;\n theme?: CodeTheme;\n className?: string;\n}\n\nexport const Code = React.forwardRef<HTMLElement, CodeProps>(\n (\n {\n children,\n language,\n inline = false,\n showLineNumbers = false,\n highlightLines = [],\n copyButton = false,\n theme = 'auto',\n className,\n },\n ref\n ) => {\n const [copied, setCopied] = React.useState(false);\n\n const handleCopy = async () => {\n try {\n await navigator.clipboard.writeText(children);\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n } catch (err) {\n console.error('Failed to copy:', err);\n }\n };\n\n if (inline) {\n return (\n <code\n ref={ref as React.Ref<HTMLElement>}\n className={cn(\n 'px-1.5 py-0.5 rounded text-sm font-mono',\n 'bg-base-200 text-base-content',\n className\n )}\n >\n {children}\n </code>\n );\n }\n\n const lines = children.split('\\n');\n const lineNumberWidth = lines.length.toString().length;\n\n return (\n <div className={cn('relative group', className)}>\n <pre\n ref={ref as React.Ref<HTMLPreElement>}\n className={cn(\n 'overflow-x-auto p-4 rounded-lg text-sm',\n 'bg-base-200 text-base-content',\n theme === 'dark' && 'bg-base-300',\n theme === 'auto' && 'dark:bg-base-300',\n showLineNumbers && 'pl-12'\n )}\n >\n {showLineNumbers && (\n <div className=\"absolute left-0 top-0 bottom-0 w-12 flex flex-col py-4 text-right pr-3 select-none\">\n {lines.map((_, index) => (\n <span\n key={index}\n className={cn(\n 'text-base-content/50 text-xs leading-6 font-mono',\n highlightLines.includes(index + 1) && 'text-primary font-semibold'\n )}\n style={{ minWidth: `${lineNumberWidth}ch` }}\n >\n {index + 1}\n </span>\n ))}\n </div>\n )}\n <code className={cn('font-mono', language && `language-${language}`)}>\n {lines.map((line, index) => (\n <div\n key={index}\n className={cn(\n 'leading-6',\n highlightLines.includes(index + 1) && 'bg-primary/10 -mx-4 px-4'\n )}\n >\n {line || '\\n'}\n </div>\n ))}\n </code>\n </pre>\n\n {copyButton && (\n <button\n onClick={handleCopy}\n className={cn(\n 'absolute top-2 right-2',\n 'btn btn-sm btn-ghost',\n 'opacity-0 group-hover:opacity-100 transition-opacity',\n 'focus:opacity-100'\n )}\n aria-label=\"Copy code\"\n >\n {copied ? (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" className=\"text-success\">\n <path\n d=\"M13.5 4.5L6 12L2.5 8.5\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n ) : (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\">\n <rect\n x=\"5.5\"\n y=\"5.5\"\n width=\"8\"\n height=\"8\"\n rx=\"1\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n />\n <path\n d=\"M10.5 5.5V3.5C10.5 2.94772 10.0523 2.5 9.5 2.5H3.5C2.94772 2.5 2.5 2.94772 2.5 3.5V9.5C2.5 10.0523 2.94772 10.5 3.5 10.5H5.5\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n />\n </svg>\n )}\n </button>\n )}\n\n {language && (\n <div className=\"absolute top-2 left-2 text-xs text-base-content/50 font-mono\">\n {language}\n </div>\n )}\n </div>\n );\n }\n);\n\nCode.displayName = 'Code';\n","import * as React from 'react';\nimport { cn } from '../../utils/cn';\n\ntype ListElement = 'ul' | 'ol';\ntype ListStyleType = 'disc' | 'circle' | 'square' | 'decimal' | 'alpha' | 'roman' | 'none';\ntype ListSpacing = 'tight' | 'normal' | 'loose';\n\nexport interface ListProps {\n as?: ListElement;\n children: React.ReactNode;\n styleType?: ListStyleType;\n spacing?: ListSpacing;\n columns?: 1 | 2 | 3 | 4;\n horizontal?: boolean;\n className?: string;\n}\n\nexport interface ListItemProps {\n children: React.ReactNode;\n icon?: React.ReactNode;\n className?: string;\n}\n\nconst styleTypeClasses: Record<ListStyleType, string> = {\n disc: 'list-disc',\n circle: 'list-circle',\n square: 'list-square',\n decimal: 'list-decimal',\n alpha: 'list-alpha',\n roman: 'list-roman',\n none: 'list-none',\n};\n\nconst spacingClasses: Record<ListSpacing, string> = {\n tight: 'space-y-1',\n normal: 'space-y-2',\n loose: 'space-y-4',\n};\n\nconst columnsClasses: Record<number, string> = {\n 1: '',\n 2: 'columns-2',\n 3: 'columns-3',\n 4: 'columns-4',\n};\n\nexport const List = React.forwardRef<HTMLUListElement | HTMLOListElement, ListProps>(\n (\n {\n as: Component = 'ul',\n children,\n styleType = Component === 'ul' ? 'disc' : 'decimal',\n spacing = 'normal',\n columns = 1,\n horizontal = false,\n className,\n },\n ref\n ) => {\n return (\n <Component\n ref={ref as any}\n className={cn(\n styleTypeClasses[styleType],\n !horizontal && spacingClasses[spacing],\n horizontal && 'flex flex-wrap gap-4',\n columnsClasses[columns],\n styleType !== 'none' && !horizontal && 'pl-5',\n 'text-base-content',\n className\n )}\n >\n {children}\n </Component>\n );\n }\n);\n\nList.displayName = 'List';\n\nexport const ListItem = React.forwardRef<HTMLLIElement, ListItemProps>(\n ({ children, icon, className }, ref) => {\n if (icon) {\n return (\n <li ref={ref} className={cn('flex items-start gap-2', className)}>\n <span className=\"flex-shrink-0 mt-0.5\" aria-hidden=\"true\">\n {icon}\n </span>\n <span>{children}</span>\n </li>\n );\n }\n\n return (\n <li ref={ref} className={className}>\n {children}\n </li>\n );\n }\n);\n\nListItem.displayName = 'ListItem';\n","import React from 'react';\nimport { Link } from '../Typography';\nimport { cn } from '../../utils/cn';\n\nexport interface LogoProps {\n /** Use gradient text with highlight effect */\n withHighlight?: boolean;\n /** Size of the logo text */\n size?: 'sm' | 'md' | 'lg' | 'xl';\n /** Whether to wrap the logo in a link */\n withLink?: boolean;\n /** Additional CSS classes */\n className?: string;\n /** Custom text to display (defaults to \"Orchard9\") */\n text?: string;\n /** Custom href for the link (defaults to \"/\") */\n href?: string;\n}\n\n/**\n * Logo component for displaying the brand name with gradient styling\n * @example\n * <Logo size=\"lg\" withHighlight />\n */\nexport const Logo: React.FC<LogoProps> = ({\n withHighlight = false,\n size = 'md',\n withLink = true,\n className,\n text = 'Orchard9',\n href = '/',\n}) => {\n const sizeClasses = {\n sm: 'text-lg',\n md: 'text-xl',\n lg: 'text-2xl',\n xl: 'text-4xl md:text-5xl',\n };\n\n const baseClasses = cn(\n 'font-bold',\n sizeClasses[size],\n 'bg-gradient-to-r from-emerald-400 to-teal-500 bg-clip-text text-transparent',\n withHighlight && 'via-emerald-300',\n className\n );\n\n const content = <span className={baseClasses}>{text}</span>;\n\n if (withLink) {\n return (\n <Link\n href={href}\n className=\"hover:opacity-80 transition-opacity inline-flex items-center gap-2\"\n >\n {content}\n </Link>\n );\n }\n\n return content;\n};\n","import * as React from 'react';\nimport { ErrorInfo } from 'react';\n\nexport interface ErrorFallbackProps {\n error: Error;\n resetErrorBoundary: () => void;\n errorInfo?: ErrorInfo;\n}\n\nexport interface ErrorBoundaryProps {\n children: React.ReactNode;\n fallback?: React.ComponentType<ErrorFallbackProps>;\n onError?: (error: Error, errorInfo: ErrorInfo) => void;\n resetKeys?: Array<string | number>;\n resetOnPropsChange?: boolean;\n isolate?: boolean;\n level?: 'page' | 'section' | 'component';\n}\n\ninterface ErrorBoundaryState {\n hasError: boolean;\n error: Error | null;\n errorInfo: ErrorInfo | null;\n}\n\nconst DefaultErrorFallback: React.FC<ErrorFallbackProps> = ({ error, resetErrorBoundary }) => {\n const isDevelopment = process.env['NODE_ENV'] === 'development';\n\n return (\n <div className=\"min-h-[200px] flex items-center justify-center p-8\">\n <div className=\"text-center max-w-md\">\n <h2 className=\"text-2xl font-bold text-error mb-4\">Something went wrong</h2>\n <p className=\"text-base-content/70 mb-6\">\n We're sorry, but something unexpected happened. Please try again.\n </p>\n\n {isDevelopment && error && (\n <details className=\"mb-6 text-left\">\n <summary className=\"cursor-pointer text-sm text-base-content/70 hover:text-base-content\">\n Error details\n </summary>\n <pre className=\"mt-2 p-4 bg-base-200 rounded text-xs overflow-auto max-h-64\">\n {error.stack || error.toString()}\n </pre>\n </details>\n )}\n\n <button onClick={resetErrorBoundary} className=\"btn btn-primary\">\n Try Again\n </button>\n </div>\n </div>\n );\n};\n\nexport class ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundaryState> {\n private resetTimeoutId: NodeJS.Timeout | null = null;\n private previousResetKeys: Array<string | number> = [];\n\n constructor(props: ErrorBoundaryProps) {\n super(props);\n this.state = {\n hasError: false,\n error: null,\n errorInfo: null,\n };\n }\n\n static getDerivedStateFromError(error: Error): Partial<ErrorBoundaryState> {\n return {\n hasError: true,\n error,\n };\n }\n\n override componentDidCatch(error: Error, errorInfo: ErrorInfo) {\n const { onError } = this.props;\n\n // Update state with error info\n this.setState({\n errorInfo,\n });\n\n // Call error handler if provided\n if (onError) {\n onError(error, errorInfo);\n }\n\n // Log error in development\n if (process.env['NODE_ENV'] === 'development') {\n console.error('ErrorBoundary caught an error:', error, errorInfo);\n }\n }\n\n override componentDidUpdate(prevProps: ErrorBoundaryProps) {\n const { resetKeys, resetOnPropsChange } = this.props;\n const { hasError } = this.state;\n\n // Reset on resetKeys change\n if (hasError && resetKeys) {\n const hasResetKeyChanged = resetKeys.some(\n (key, index) => key !== this.previousResetKeys[index]\n );\n\n if (hasResetKeyChanged) {\n this.resetErrorBoundary();\n }\n }\n\n // Reset on any props change if enabled\n if (hasError && resetOnPropsChange && prevProps !== this.props) {\n this.resetErrorBoundary();\n }\n\n this.previousResetKeys = resetKeys || [];\n }\n\n override componentWillUnmount() {\n if (this.resetTimeoutId) {\n clearTimeout(this.resetTimeoutId);\n }\n }\n\n resetErrorBoundary = () => {\n this.setState({\n hasError: false,\n error: null,\n errorInfo: null,\n });\n };\n\n override render() {\n const { hasError, error, errorInfo } = this.state;\n const { fallback: Fallback = DefaultErrorFallback, children, isolate, level } = this.props;\n\n if (hasError && error) {\n const errorBoundaryClass = isolate\n ? 'error-boundary-isolated'\n : `error-boundary-${level || 'component'}`;\n\n return (\n <div className={errorBoundaryClass}>\n <Fallback\n error={error}\n {...(errorInfo ? { errorInfo } : {})}\n resetErrorBoundary={this.resetErrorBoundary}\n />\n </div>\n );\n }\n\n return children;\n }\n}\n","import * as React from 'react';\nimport { cn } from '../../utils/cn';\nimport { Button } from '../Button/Button';\n\nexport interface ErrorAction {\n label: string;\n href?: string;\n onClick?: () => void;\n variant?: 'primary' | 'secondary' | 'ghost';\n icon?: React.ReactNode;\n}\n\nexport interface ErrorPageProps {\n code?: 404 | 500 | 403 | 401 | number;\n title?: string;\n description?: string;\n illustration?: React.ReactNode;\n actions?: ErrorAction[];\n showDetails?: boolean;\n error?: Error;\n className?: string;\n}\n\n// Default illustrations as simple SVG components\nconst NotFoundIllustration = () => (\n <svg className=\"w-64 h-64\" viewBox=\"0 0 256 256\" fill=\"none\">\n <circle cx=\"128\" cy=\"128\" r=\"96\" stroke=\"currentColor\" strokeWidth=\"8\" opacity=\"0.2\" />\n <path\n d=\"M88 104C88 95.1634 95.1634 88 104 88H152C160.837 88 168 95.1634 168 104V104C168 112.837 160.837 120 152 120H104C95.1634 120 88 112.837 88 104V104Z\"\n fill=\"currentColor\"\n opacity=\"0.3\"\n />\n <rect x=\"88\" y=\"136\" width=\"80\" height=\"16\" rx=\"8\" fill=\"currentColor\" opacity=\"0.3\" />\n <rect x=\"104\" y=\"168\" width=\"48\" height=\"16\" rx=\"8\" fill=\"currentColor\" opacity=\"0.3\" />\n </svg>\n);\n\nconst ServerErrorIllustration = () => (\n <svg className=\"w-64 h-64\" viewBox=\"0 0 256 256\" fill=\"none\">\n <rect\n x=\"64\"\n y=\"80\"\n width=\"128\"\n height=\"96\"\n rx=\"8\"\n stroke=\"currentColor\"\n strokeWidth=\"8\"\n opacity=\"0.2\"\n />\n <circle cx=\"88\" cy=\"104\" r=\"8\" fill=\"currentColor\" opacity=\"0.5\" />\n <circle cx=\"112\" cy=\"104\" r=\"8\" fill=\"currentColor\" opacity=\"0.5\" />\n <circle cx=\"136\" cy=\"104\" r=\"8\" fill=\"currentColor\" opacity=\"0.5\" />\n <path\n d=\"M88 128H168M88 144H168M88 160H168\"\n stroke=\"currentColor\"\n strokeWidth=\"8\"\n strokeLinecap=\"round\"\n opacity=\"0.3\"\n />\n </svg>\n);\n\nconst ForbiddenIllustration = () => (\n <svg className=\"w-64 h-64\" viewBox=\"0 0 256 256\" fill=\"none\">\n <circle cx=\"128\" cy=\"128\" r=\"96\" stroke=\"currentColor\" strokeWidth=\"8\" opacity=\"0.2\" />\n <path\n d=\"M128 88V144M128 168V176\"\n stroke=\"currentColor\"\n strokeWidth=\"16\"\n strokeLinecap=\"round\"\n opacity=\"0.5\"\n />\n </svg>\n);\n\nconst UnauthorizedIllustration = () => (\n <svg className=\"w-64 h-64\" viewBox=\"0 0 256 256\" fill=\"none\">\n <rect\n x=\"88\"\n y=\"96\"\n width=\"80\"\n height=\"96\"\n rx=\"8\"\n stroke=\"currentColor\"\n strokeWidth=\"8\"\n opacity=\"0.2\"\n />\n <circle cx=\"128\" cy=\"120\" r=\"16\" fill=\"currentColor\" opacity=\"0.3\" />\n <path\n d=\"M112 144C112 135.163 119.163 128 128 128V128C136.837 128 144 135.163 144 144V168\"\n stroke=\"currentColor\"\n strokeWidth=\"8\"\n strokeLinecap=\"round\"\n opacity=\"0.3\"\n />\n </svg>\n);\n\nconst errorTemplates = {\n 404: {\n title: 'Page Not Found',\n description: \"The page you're looking for doesn't exist or has been moved.\",\n illustration: <NotFoundIllustration />,\n actions: [\n { label: 'Go Home', href: '/', variant: 'primary' as const },\n { label: 'Go Back', onClick: () => window.history.back(), variant: 'secondary' as const },\n ],\n },\n 500: {\n title: 'Something Went Wrong',\n description: \"We're having technical difficulties. Please try again later.\",\n illustration: <ServerErrorIllustration />,\n actions: [\n { label: 'Retry', onClick: () => window.location.reload(), variant: 'primary' as const },\n { label: 'Go Home', href: '/', variant: 'secondary' as const },\n ],\n },\n 403: {\n title: 'Access Denied',\n description: \"You don't have permission to view this page.\",\n illustration: <ForbiddenIllustration />,\n actions: [\n { label: 'Go Home', href: '/', variant: 'primary' as const },\n { label: 'Contact Support', href: '/support', variant: 'secondary' as const },\n ],\n },\n 401: {\n title: 'Authentication Required',\n description: 'Please log in to access this page.',\n illustration: <UnauthorizedIllustration />,\n actions: [\n { label: 'Log In', href: '/login', variant: 'primary' as const },\n { label: 'Go Home', href: '/', variant: 'secondary' as const },\n ],\n },\n};\n\nexport const ErrorPage = React.forwardRef<HTMLDivElement, ErrorPageProps>(\n (\n {\n code = 404,\n title,\n description,\n illustration,\n actions,\n showDetails = false,\n error,\n className,\n },\n ref\n ) => {\n const template = errorTemplates[code as keyof typeof errorTemplates] || errorTemplates[404];\n const finalTitle = title || template.title;\n const finalDescription = description || template.description;\n const finalIllustration = illustration || template.illustration;\n const finalActions = actions || template.actions;\n\n const isDevelopment =\n typeof process !== 'undefined' && process.env && process.env['NODE_ENV'] === 'development';\n\n return (\n <div\n ref={ref}\n className={cn(\n 'min-h-screen flex items-center justify-center p-4',\n 'bg-base-100',\n className\n )}\n >\n <div className=\"max-w-md w-full text-center relative\">\n {/* Illustration - Absolutely positioned and centered */}\n <div className=\"absolute inset-0 flex items-center justify-center pointer-events-none\">\n <div className=\"text-base-content\">{finalIllustration}</div>\n </div>\n\n {/* Content - Relative positioned to appear above illustration */}\n <div className=\"relative z-10\">\n {/* Error Code */}\n <div className=\"text-6xl font-bold text-base-content/80 mb-4\">{code}</div>\n\n {/* Title */}\n <h1 className=\"text-2xl font-bold mb-2 text-base-content\">{finalTitle}</h1>\n\n {/* Description */}\n <p className=\"text-base-content/70 mb-8\">{finalDescription}</p>\n\n {/* Actions */}\n <div className=\"flex flex-col sm:flex-row gap-4 justify-center\">\n {finalActions.map((action, index) => {\n if ('href' in action && action.href) {\n return (\n <a\n key={index}\n href={action.href}\n className={cn(\n 'btn',\n action.variant && `btn-${action.variant}`,\n 'inline-flex items-center justify-center gap-2'\n )}\n >\n {'icon' in action && action.icon && action.icon}\n {action.label}\n </a>\n );\n }\n return (\n <Button\n key={index}\n variant={action.variant || 'primary'}\n onClick={'onClick' in action ? action.onClick : undefined}\n className=\"inline-flex items-center justify-center gap-2\"\n >\n {'icon' in action && action.icon && action.icon}\n {action.label}\n </Button>\n );\n })}\n </div>\n\n {/* Error Details (dev mode) */}\n {showDetails && error && isDevelopment && (\n <details className=\"mt-8 text-left\">\n <summary className=\"cursor-pointer text-sm text-base-content/70 hover:text-base-content\">\n Technical Details\n </summary>\n <pre className=\"mt-2 p-4 bg-base-200 rounded text-xs overflow-auto max-h-64\">\n {error.stack || error.toString()}\n </pre>\n </details>\n )}\n </div>\n </div>\n </div>\n );\n }\n);\n\nErrorPage.displayName = 'ErrorPage';\n","import React from 'react';\nimport { cn } from '../../utils/cn';\n\nexport interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n variant?:\n | 'primary'\n | 'secondary'\n | 'accent'\n | 'info'\n | 'success'\n | 'warning'\n | 'error'\n | 'ghost'\n | 'link'\n | 'outline'\n | 'neutral';\n size?: 'xs' | 'sm' | 'md' | 'lg';\n shape?: 'default' | 'square' | 'circle';\n loading?: boolean | { text?: string };\n fullWidth?: boolean;\n active?: boolean;\n glass?: boolean;\n noAnimation?: boolean;\n as?: React.ElementType;\n startIcon?: React.ReactNode;\n endIcon?: React.ReactNode;\n}\n\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n (\n {\n variant,\n size = 'md',\n shape = 'default',\n loading = false,\n fullWidth = false,\n active = false,\n glass = false,\n noAnimation = false,\n as: Component = 'button',\n startIcon,\n endIcon,\n children,\n className,\n disabled,\n ...props\n },\n ref\n ) => {\n const isLoading = !!loading;\n const loadingText = typeof loading === 'object' ? loading.text : undefined;\n\n const classes = cn(\n 'btn',\n 'focus-interactive', // Use standardized focus utilities\n // Variants\n variant === 'primary' && 'btn-primary',\n variant === 'secondary' && 'btn-secondary',\n variant === 'accent' && 'btn-accent',\n variant === 'info' && 'btn-info',\n variant === 'success' && 'btn-success',\n variant === 'warning' && 'btn-warning',\n variant === 'error' && 'btn-error',\n variant === 'ghost' && 'btn-ghost',\n variant === 'link' && 'btn-link',\n variant === 'outline' && 'btn-outline',\n variant === 'neutral' && 'btn-neutral',\n // Sizes\n size === 'xs' && 'btn-xs',\n size === 'sm' && 'btn-sm',\n size === 'lg' && 'btn-lg',\n // Shapes\n shape === 'square' && 'btn-square',\n shape === 'circle' && 'btn-circle',\n // States\n active && 'btn-active',\n glass && 'glass',\n noAnimation && 'no-animation',\n fullWidth && 'btn-block',\n className\n );\n\n return (\n <Component ref={ref} className={classes} disabled={disabled || isLoading} {...props}>\n {isLoading && <span className=\"loading loading-spinner loading-xs\"></span>}\n {startIcon && !isLoading && <span className=\"btn-start-icon\">{startIcon}</span>}\n {loadingText && isLoading ? loadingText : children}\n {endIcon && !isLoading && <span className=\"btn-end-icon\">{endIcon}</span>}\n </Component>\n );\n }\n);\n\nButton.displayName = 'Button';\nexport { Button };\n","import * as React from 'react';\nimport { cn } from '../../utils/cn';\n\ntype ErrorMessageVariant = 'error' | 'warning' | 'info';\n\nexport interface ErrorMessageProps {\n error?: string | Error | null;\n errors?: string[] | Error[];\n icon?: React.ReactNode;\n dismissible?: boolean;\n onDismiss?: () => void;\n className?: string;\n variant?: ErrorMessageVariant;\n}\n\nconst defaultIcons: Record<ErrorMessageVariant, React.ReactNode> = {\n error: (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" className=\"flex-shrink-0\">\n <circle cx=\"8\" cy=\"8\" r=\"7\" stroke=\"currentColor\" strokeWidth=\"2\" />\n <path d=\"M8 5V9M8 11V11.5\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" />\n </svg>\n ),\n warning: (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" className=\"flex-shrink-0\">\n <path\n d=\"M7.2 3.5C7.6 2.8 8.4 2.8 8.8 3.5L14.4 13C14.8 13.7 14.4 14.5 13.6 14.5H2.4C1.6 14.5 1.2 13.7 1.6 13L7.2 3.5Z\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinejoin=\"round\"\n />\n <path d=\"M8 6V9M8 11.5V12\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" />\n </svg>\n ),\n info: (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" className=\"flex-shrink-0\">\n <circle cx=\"8\" cy=\"8\" r=\"7\" stroke=\"currentColor\" strokeWidth=\"2\" />\n <path d=\"M8 7V11M8 5V5.5\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" />\n </svg>\n ),\n};\n\nconst variantClasses: Record<ErrorMessageVariant, string> = {\n error: 'text-error border-error/20 bg-error/10',\n warning: 'text-warning border-warning/20 bg-warning/10',\n info: 'text-info border-info/20 bg-info/10',\n};\n\nexport const ErrorMessage = React.forwardRef<HTMLDivElement, ErrorMessageProps>(\n ({ error, errors, icon, dismissible = false, onDismiss, className, variant = 'error' }, ref) => {\n const [isVisible, setIsVisible] = React.useState(true);\n\n // Normalize errors into array\n const errorList = React.useMemo(() => {\n if (errors) {\n return errors.map((e) => (e instanceof Error ? e.message : e));\n }\n if (error) {\n return [error instanceof Error ? error.message : error];\n }\n return [];\n }, [error, errors]);\n\n const handleDismiss = () => {\n setIsVisible(false);\n onDismiss?.();\n };\n\n if (!isVisible || errorList.length === 0) {\n return null;\n }\n\n const finalIcon = icon || defaultIcons[variant];\n\n return (\n <div\n ref={ref}\n role=\"alert\"\n className={cn(\n 'relative flex gap-3 p-3 rounded-lg border',\n variantClasses[variant],\n 'animate-in fade-in slide-in-from-top-1 duration-200',\n className\n )}\n >\n {finalIcon && <div className=\"mt-0.5\">{finalIcon}</div>}\n\n <div className=\"flex-1 space-y-1\">\n {errorList.map((msg, index) => (\n <div key={index} className=\"text-sm\">\n {msg}\n </div>\n ))}\n </div>\n\n {dismissible && (\n <button\n onClick={handleDismiss}\n className=\"flex-shrink-0 p-0.5 hover:bg-base-content/10 rounded transition-colors\"\n aria-label=\"Dismiss error\"\n >\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path\n d=\"M12 4L4 12M4 4L12 12\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n />\n </svg>\n </button>\n )}\n </div>\n );\n }\n);\n\nErrorMessage.displayName = 'ErrorMessage';\n","import React from 'react';\nimport { cn } from '../../utils/cn';\n\nexport interface ButtonGroupProps {\n children: React.ReactNode;\n vertical?: boolean;\n className?: string;\n}\n\nexport const ButtonGroup: React.FC<ButtonGroupProps> = ({\n children,\n vertical = false,\n className,\n}) => {\n return (\n <div className={cn('btn-group', vertical && 'btn-group-vertical', className)}>{children}</div>\n );\n};\n","import React, { createContext, useContext, useEffect, useState, useCallback, useMemo } from 'react';\nimport { Theme, ThemeContext as IThemeContext, ThemeColors, ThemeProviderProps } from './types';\n\nconst ThemeContext = createContext<IThemeContext | undefined>(undefined);\n\n// Script to inject for preventing FOUC\n// Can be customized with defaultTheme parameter\nexport const themeInitScript = (defaultTheme?: string) => `\n (function() {\n const theme = localStorage.getItem('theme');\n const systemTheme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';\n const fallbackTheme = ${defaultTheme ? `'${defaultTheme}'` : 'systemTheme'};\n document.documentElement.setAttribute('data-theme', theme || fallbackTheme);\n })();\n`;\n\n/**\n * ThemeProvider with automatic localStorage persistence and system preference detection.\n *\n * @example\n * // Basic usage - themes are automatically persisted\n * <ThemeProvider defaultTheme=\"grove-light\">\n * <App />\n * </ThemeProvider>\n *\n * // With theme change callback\n * <ThemeProvider\n * defaultTheme=\"grove-dark\"\n * onThemeChange={(theme) => analytics.track('theme_changed', { theme })}\n * >\n * <App />\n * </ThemeProvider>\n *\n * // Access theme state in components\n * const { theme, setTheme, themes } = useTheme();\n *\n * @param props - ThemeProvider configuration\n * @param props.children - Child components to wrap\n * @param props.defaultTheme - Default theme when no stored preference exists\n * @param props.initialTheme - Override theme for testing/Storybook (skips persistence)\n * @param props.onThemeChange - Callback fired when theme changes\n * @param props.disableInitialTransition - Prevent transition animation on initial load (default: true)\n */\nexport const ThemeProvider: React.FC<ThemeProviderProps> = ({\n children,\n defaultTheme = 'light',\n initialTheme,\n onThemeChange,\n disableInitialTransition = true,\n}) => {\n // Development-time prop validation\n if (typeof process !== 'undefined' && process.env && process.env['NODE_ENV'] === 'development') {\n // Check for common mistakes\n const propsToValidate = {\n children,\n defaultTheme,\n initialTheme,\n onThemeChange,\n disableInitialTransition,\n };\n const invalidProps = Object.keys(propsToValidate as Record<string, unknown>).filter(\n (key) =>\n ![\n 'children',\n 'defaultTheme',\n 'initialTheme',\n 'onThemeChange',\n 'disableInitialTransition',\n ].includes(key)\n );\n\n if (invalidProps.length > 0) {\n console.warn(\n `ThemeProvider: Invalid props detected: ${invalidProps.join(', ')}.\\n` +\n `Valid props are: children, defaultTheme, initialTheme, onThemeChange, disableInitialTransition.\\n` +\n `See docs: https://design-system.orchard9.ai/theme`\n );\n }\n\n if (\n defaultTheme &&\n !['light', 'dark', 'cupcake', 'business', 'grove-light', 'grove-dark', 'dawn', 'dusk'].includes(defaultTheme)\n ) {\n console.warn(\n `ThemeProvider: Invalid defaultTheme \"${defaultTheme}\".\\n` +\n `Valid themes are: light, dark, cupcake, business, grove-light, grove-dark, dawn, dusk.`\n );\n }\n }\n\n const [theme, setThemeState] = useState<Theme>(initialTheme || defaultTheme);\n const [systemTheme, setSystemTheme] = useState<'light' | 'dark'>('light');\n const [colors, setColors] = useState<ThemeColors>({} as ThemeColors);\n const [isInitialized, setIsInitialized] = useState(false);\n\n const themes = useMemo<Theme[]>(\n () => ['light', 'dark', 'cupcake', 'business', 'grove-light', 'grove-dark', 'dawn', 'dusk'],\n []\n );\n\n // Get computed theme colors\n const updateColors = useCallback(() => {\n const computed = getComputedStyle(document.documentElement);\n const newColors: Partial<ThemeColors> = {};\n\n // DaisyUI color variables\n const colorVars = [\n 'primary',\n 'primary-focus',\n 'primary-content',\n 'secondary',\n 'secondary-focus',\n 'secondary-content',\n 'accent',\n 'accent-focus',\n 'accent-content',\n 'neutral',\n 'neutral-focus',\n 'neutral-content',\n 'base-100',\n 'base-200',\n 'base-300',\n 'base-content',\n 'info',\n 'success',\n 'warnin