{
  "generatedAt": "2026-07-04T10:41:14.352Z",
  "library": {
    "name": "fluxo-ui",
    "version": "0.4.93",
    "description": "A comprehensive, accessible React component library built with TypeScript. Includes 100+ production-ready UI components, a custom state management solution, dependency injection container, 12 color themes, dark mode, and full keyboard navigation.",
    "homepage": "https://fluxo-ui.utilsware.com/"
  },
  "entryPoints": [
    ".",
    "./hooks",
    "./icons",
    "./store",
    "./store/middlewares",
    "./utils",
    "./draw",
    "./services",
    "./vite-plugin",
    "./report-builder",
    "./report-viewer",
    "./chat"
  ],
  "components": {
    "Autocomplete": {
      "name": "Autocomplete",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React, { useState } from 'react';\nimport { Autocomplete } from '../../../components';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { suggestions } from './autocomplete-story-data';\n\nconst BasicUsage: React.FC = () => {\n    const [basicValue, setBasicValue] = useState('');\n\n    return (\n        <ComponentDemo title=\"Basic Autocomplete\" description=\"Simple autocomplete with a list of suggestions\">\n            <div className=\"w-full max-w-80\">\n                <Autocomplete\n                    items={suggestions}\n                    value={basicValue}\n                    placeholder=\"Type to search fruits...\"\n                    onChange={(e) => setBasicValue(e.value)}\n                />\n            </div>\n        </ComponentDemo>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "CustomConfiguration",
          "code": "import React, { useState } from 'react';\nimport { Autocomplete } from '../../../components';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { suggestions } from './autocomplete-story-data';\n\nconst CustomConfiguration: React.FC = () => {\n    const [customValue, setCustomValue] = useState('');\n\n    return (\n        <ComponentDemo title=\"Custom Configuration\" description=\"Autocomplete with custom minLength and maxSuggestions\">\n            <div className=\"w-full max-w-80\">\n                <Autocomplete\n                    items={suggestions}\n                    value={customValue}\n                    placeholder=\"Min 2 chars, max 3 suggestions...\"\n                    minLength={2}\n                    maxSuggestions={3}\n                    onChange={(e) => setCustomValue(e.value)}\n                    onSelect={(suggestion) => console.log('Selected:', suggestion)}\n                />\n            </div>\n        </ComponentDemo>\n    );\n};\n\nexport default CustomConfiguration;\n"
        },
        {
          "title": "DisabledState",
          "code": "import React from 'react';\nimport { Autocomplete } from '../../../components';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { suggestions } from './autocomplete-story-data';\n\nconst DisabledState: React.FC = () => {\n    return (\n        <ComponentDemo title=\"Disabled State\" description=\"Autocomplete in disabled state\">\n            <div className=\"w-full max-w-80\">\n                <Autocomplete items={suggestions} value=\"Disabled input\" disabled />\n            </div>\n        </ComponentDemo>\n    );\n};\n\nexport default DisabledState;\n"
        },
        {
          "title": "UsageExamples",
          "code": "import cn from 'classnames';\nimport React from 'react';\nimport { CodeBlock } from '../../CodeBlock';\nimport { useStoryTheme } from '../../StoryThemeContext';\nimport { basicUsageCode, advancedUsageCode } from './autocomplete-story-data';\n\nconst UsageExamples: React.FC = () => {\n    const { isDark } = useStoryTheme();\n\n    return (\n        <>\n            <div className=\"space-y-4\">\n                <h3 className={cn('text-lg font-medium', { 'text-gray-300': isDark, 'text-gray-700': !isDark })}>Basic Usage</h3>\n                <CodeBlock code={basicUsageCode} language=\"typescript\" />\n            </div>\n\n            <div className=\"mt-6 space-y-4\">\n                <h3 className={cn('text-lg font-medium', { 'text-gray-300': isDark, 'text-gray-700': !isDark })}>Advanced Usage</h3>\n                <CodeBlock code={advancedUsageCode} language=\"typescript\" />\n            </div>\n        </>\n    );\n};\n\nexport default UsageExamples;\n"
        }
      ],
      "props": {
        "autocompleteProps": {
          "items": {
            "type": "ListItem[]",
            "required": true,
            "description": "Array of suggestion items with { label: string, value: any } structure"
          },
          "value": {
            "type": "string",
            "default": "''",
            "description": "Current input value (controlled)"
          },
          "selectedValue": {
            "type": "any",
            "description": "Currently selected item value"
          },
          "onChange": {
            "type": "(event: ComponentEvent<string>) => void",
            "description": "Callback fired when input value changes. Receives event object with value, name, and args"
          },
          "onSelect": {
            "type": "(event: ComponentEvent<any>) => void",
            "description": "Callback fired when a suggestion is selected. Receives the selected item value"
          },
          "onFilter": {
            "type": "(query: string) => void | Promise<void>",
            "description": "Callback for filtering items or loading async data based on input"
          },
          "placeholder": {
            "type": "string",
            "default": "'Type to search...'",
            "description": "Placeholder text for the input"
          },
          "required": {
            "type": "boolean",
            "default": "false",
            "description": "Mark the input as required"
          },
          "readonly": {
            "type": "boolean",
            "default": "false",
            "description": "Make the input read-only"
          },
          "disabled": {
            "type": "boolean",
            "default": "false",
            "description": "Disable the input"
          },
          "minLength": {
            "type": "number",
            "default": "1",
            "description": "Minimum characters before showing suggestions"
          },
          "maxSuggestions": {
            "type": "number",
            "description": "Maximum number of suggestions to display (filters the items list)"
          },
          "debounceMs": {
            "type": "number",
            "default": "300",
            "description": "Debounce delay in milliseconds before calling onFilter"
          },
          "loading": {
            "type": "boolean",
            "default": "false",
            "description": "Show loading indicator in the input"
          },
          "emptyMessage": {
            "type": "string",
            "default": "'No results found'",
            "description": "Message shown when no suggestions match"
          },
          "renderItem": {
            "type": "(item: ListItem, index: number, isSelected: boolean, isHighlighted: boolean) => ReactNode",
            "description": "Custom renderer for suggestion items"
          },
          "autoFocus": {
            "type": "boolean",
            "default": "false",
            "description": "Auto focus the input on mount"
          },
          "id": {
            "type": "string",
            "description": "HTML id attribute for the input"
          },
          "name": {
            "type": "string",
            "description": "Name attribute for the input (used in forms)"
          },
          "args": {
            "type": "any",
            "description": "Additional arguments passed to onChange/onSelect handlers"
          },
          "className": {
            "type": "string",
            "description": "Additional CSS classes for the input"
          }
        }
      },
      "storyDir": "autocomplete"
    },
    "AutocompleteMulti": {
      "name": "AutocompleteMulti",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React, { useState } from 'react';\nimport { AutocompleteMulti } from '../../../components';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { suggestions } from './autocomplete-multi-story-data';\n\nconst BasicUsage: React.FC = () => {\n    const [basicValues, setBasicValues] = useState<string[]>([]);\n\n    return (\n        <ComponentDemo title=\"Basic Multi-Select Autocomplete\" description=\"Select multiple items with autocomplete functionality\">\n            <div className=\"w-full max-w-96\">\n                <AutocompleteMulti\n                    items={suggestions}\n                    value={basicValues}\n                    placeholder=\"Type to search and select fruits...\"\n                    onChange={(e) => setBasicValues(e.value)}\n                />\n            </div>\n        </ComponentDemo>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "DisabledState",
          "code": "import React from 'react';\nimport { AutocompleteMulti } from '../../../components';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { suggestions } from './autocomplete-multi-story-data';\n\nconst DisabledState: React.FC = () => {\n    return (\n        <ComponentDemo title=\"Disabled State\" description=\"AutocompleteMulti in disabled state\">\n            <div className=\"w-full max-w-96\">\n                <AutocompleteMulti items={suggestions} value={['Apple', 'Banana']} disabled />\n            </div>\n        </ComponentDemo>\n    );\n};\n\nexport default DisabledState;\n"
        },
        {
          "title": "LimitedSelections",
          "code": "import React from 'react';\nimport { AutocompleteMulti } from '../../../components';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { suggestions } from './autocomplete-multi-story-data';\n\nconst LimitedSelections: React.FC = () => {\n    return (\n        <ComponentDemo title=\"Limited Selections\" description=\"Maximum 3 selections allowed\">\n            <div className=\"w-full max-w-96\">\n                <AutocompleteMulti\n                    items={suggestions}\n                    value={[]}\n                    placeholder=\"Max 3 selections...\"\n                    maxSelectedItems={3}\n                    onChange={(e) => console.log('Changed:', e.value)}\n                />\n            </div>\n        </ComponentDemo>\n    );\n};\n\nexport default LimitedSelections;\n"
        },
        {
          "title": "PresetValues",
          "code": "import React, { useState } from 'react';\nimport { AutocompleteMulti } from '../../../components';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { suggestions } from './autocomplete-multi-story-data';\n\nconst PresetValues: React.FC = () => {\n    const [customValues, setCustomValues] = useState<string[]>(['Apple']);\n\n    return (\n        <ComponentDemo title=\"With Preset Values\" description=\"Autocomplete with pre-selected values\">\n            <div className=\"w-full max-w-96\">\n                <AutocompleteMulti\n                    items={suggestions}\n                    value={customValues}\n                    placeholder=\"Add more fruits...\"\n                    onChange={(e) => setCustomValues(e.value)}\n                />\n            </div>\n        </ComponentDemo>\n    );\n};\n\nexport default PresetValues;\n"
        },
        {
          "title": "UsageExamples",
          "code": "import cn from 'classnames';\nimport React from 'react';\nimport { CodeBlock } from '../../CodeBlock';\nimport { useStoryTheme } from '../../StoryThemeContext';\nimport { basicUsageCode, advancedUsageCode } from './autocomplete-multi-story-data';\n\nconst UsageExamples: React.FC = () => {\n    const { isDark } = useStoryTheme();\n\n    return (\n        <>\n            <div className=\"space-y-4\">\n                <h3 className={cn('text-lg font-medium', { 'text-gray-300': isDark, 'text-gray-700': !isDark })}>Basic Usage</h3>\n                <CodeBlock code={basicUsageCode} language=\"typescript\" />\n            </div>\n\n            <div className=\"mt-6 space-y-4\">\n                <h3 className={cn('text-lg font-medium', { 'text-gray-300': isDark, 'text-gray-700': !isDark })}>Advanced Usage</h3>\n                <CodeBlock code={advancedUsageCode} language=\"typescript\" />\n            </div>\n        </>\n    );\n};\n\nexport default UsageExamples;\n"
        }
      ],
      "props": {
        "autocompleteMultiProps": {
          "items": {
            "type": "ListItem[]",
            "required": true,
            "description": "Array of items to display in suggestions"
          },
          "value": {
            "type": "T[]",
            "description": "Array of selected values"
          },
          "onChange": {
            "type": "function",
            "description": "Callback fired when values change: (event: ComponentEvent<T[]>) => void"
          },
          "onFilter": {
            "type": "function",
            "description": "Callback fired when filter input changes: (query: string) => void | Promise<void>"
          },
          "placeholder": {
            "type": "string",
            "default": "Type to search and select...",
            "description": "Placeholder text for the input field"
          },
          "disabled": {
            "type": "boolean",
            "default": false,
            "description": "Whether the input is disabled"
          },
          "readonly": {
            "type": "boolean",
            "default": false,
            "description": "Whether the input is readonly"
          },
          "required": {
            "type": "boolean",
            "default": false,
            "description": "Whether the field is required"
          },
          "debounceMs": {
            "type": "number",
            "default": 300,
            "description": "Debounce delay in milliseconds for filter callback"
          },
          "minLength": {
            "type": "number",
            "default": 1,
            "description": "Minimum characters before showing suggestions"
          },
          "maxSelectedItems": {
            "type": "number",
            "description": "Maximum number of items that can be selected"
          },
          "loading": {
            "type": "boolean",
            "default": false,
            "description": "Whether data is loading"
          },
          "emptyMessage": {
            "type": "string",
            "default": "No results found",
            "description": "Message shown when no items match the filter"
          },
          "renderItem": {
            "type": "function",
            "description": "Custom render function for each item: (item: ListItem, index: number, isSelected: boolean, isHighlighted: boolean) => React.ReactNode"
          },
          "renderSelectedTemplate": {
            "type": "function",
            "description": "Custom render function for selected items: (selectedItems: ListItem[], onRemove: (value: T) => void) => React.ReactNode"
          },
          "showCount": {
            "type": "boolean",
            "default": false,
            "description": "Show count of selected items when more than 3 are selected"
          },
          "autoFocus": {
            "type": "boolean",
            "default": false,
            "description": "Auto-focus the input field on mount"
          },
          "id": {
            "type": "string",
            "description": "ID for the input element"
          },
          "name": {
            "type": "string",
            "description": "Name attribute for the hidden input field"
          },
          "args": {
            "type": "any",
            "description": "Additional arguments passed to event callbacks"
          }
        }
      },
      "storyDir": "autocomplete-multi"
    },
    "Breadcrumb": {
      "name": "Breadcrumb",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React from 'react';\nimport type { BreadcrumbItem } from '../../../components';\nimport { Breadcrumb } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst items: BreadcrumbItem[] = [\n    { label: 'Home', href: '#' },\n    { label: 'Products', href: '#' },\n    { label: 'Electronics', href: '#' },\n    { label: 'Laptops' },\n];\n\nconst code = `import { Breadcrumb } from 'fluxo-ui';\nimport type { BreadcrumbItem } from 'fluxo-ui';\n\nconst items: BreadcrumbItem[] = [\n  { label: 'Home', href: '/' },\n  { label: 'Products', href: '/products' },\n  { label: 'Electronics', href: '/products/electronics' },\n  { label: 'Laptops' },\n];\n\n<Breadcrumb\n  items={items}\n  onItemClick={(item, index) => console.log(item.label, index)}\n/>`;\n\nconst BasicUsage: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Standard Breadcrumb\" description=\"A simple breadcrumb trail with the last item as the current page.\">\n            <Breadcrumb items={items} onItemClick={(item, index) => console.log('Clicked:', item.label, index)} />\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default BasicUsage;\n"
        },
        {
          "title": "CollapsedItems",
          "code": "import React from 'react';\nimport type { BreadcrumbItem } from '../../../components';\nimport { Breadcrumb } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst items: BreadcrumbItem[] = [\n    { label: 'Home', href: '#' },\n    { label: 'Region', href: '#' },\n    { label: 'Country', href: '#' },\n    { label: 'State', href: '#' },\n    { label: 'City', href: '#' },\n    { label: 'District', href: '#' },\n    { label: 'Street' },\n];\n\nconst code = `import { Breadcrumb } from 'fluxo-ui';\n\nconst items = [\n  { label: 'Home', href: '/' },\n  { label: 'Region', href: '/region' },\n  { label: 'Country', href: '/country' },\n  { label: 'State', href: '/state' },\n  { label: 'City', href: '/city' },\n  { label: 'District', href: '/district' },\n  { label: 'Street' },\n];\n\n<Breadcrumb items={items} maxItems={3} />`;\n\nconst CollapsedItems: React.FC = () => (\n    <>\n        <ComponentDemo\n            title=\"Collapsed Items\"\n            description=\"When maxItems is set, middle items collapse into an ellipsis dropdown. Click the ellipsis to expand.\"\n        >\n            <Breadcrumb items={items} maxItems={3} />\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default CollapsedItems;\n"
        },
        {
          "title": "CustomSeparator",
          "code": "import React from 'react';\nimport type { BreadcrumbItem } from '../../../components';\nimport { Breadcrumb } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst items: BreadcrumbItem[] = [\n    { label: 'Dashboard', href: '#' },\n    { label: 'Settings', href: '#' },\n    { label: 'Security', href: '#' },\n    { label: 'Two-Factor Auth' },\n];\n\nconst arrowSeparator = (\n    <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}>\n        <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M9 5l7 7-7 7\" />\n    </svg>\n);\n\nconst code = `import { Breadcrumb } from 'fluxo-ui';\n\nconst arrowSeparator = (\n  <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n    <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M9 5l7 7-7 7\" />\n  </svg>\n);\n\n<Breadcrumb items={items} separator={arrowSeparator} />\n\n<Breadcrumb items={items} separator=\">\" />\n\n<Breadcrumb items={items} separator=\"|\" />`;\n\nconst CustomSeparator: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Custom Separators\" description=\"Use any ReactNode as a separator between breadcrumb items.\">\n            <div className=\"space-y-4\">\n                <div>\n                    <span className=\"text-sm text-gray-500 mb-1 block\">Arrow icon separator</span>\n                    <Breadcrumb items={items} separator={arrowSeparator} />\n                </div>\n                <div>\n                    <span className=\"text-sm text-gray-500 mb-1 block\">Greater-than separator</span>\n                    <Breadcrumb items={items} separator=\">\" />\n                </div>\n                <div>\n                    <span className=\"text-sm text-gray-500 mb-1 block\">Pipe separator</span>\n                    <Breadcrumb items={items} separator=\"|\" />\n                </div>\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default CustomSeparator;\n"
        }
      ],
      "props": {
        "breadcrumbProps": {
          "items": {
            "type": "BreadcrumbItem[]",
            "required": true,
            "description": "Array of breadcrumb items to display."
          },
          "separator": {
            "type": "ReactNode",
            "default": "'/'",
            "description": "Custom separator between items."
          },
          "maxItems": {
            "type": "number",
            "description": "Maximum visible items before collapsing middle items into ellipsis. When omitted, the breadcrumb auto-collapses based on container width unless autoCollapse is explicitly false."
          },
          "autoCollapse": {
            "type": "boolean",
            "default": "true",
            "description": "Auto-collapse middle items when the breadcrumb overflows its container. Ignored when maxItems is provided."
          },
          "className": {
            "type": "string",
            "description": "Additional CSS class for the nav container."
          },
          "onItemClick": {
            "type": "(item: BreadcrumbItem, index: number) => void",
            "description": "Called when any breadcrumb item is clicked."
          }
        },
        "itemProps": {
          "label": {
            "type": "string",
            "required": true,
            "description": "Display text for the breadcrumb."
          },
          "href": {
            "type": "string",
            "description": "URL for the breadcrumb link."
          },
          "icon": {
            "type": "ReactNode",
            "description": "Icon displayed before the label."
          },
          "onClick": {
            "type": "() => void",
            "description": "Click handler for the item."
          }
        }
      },
      "storyDir": "breadcrumb"
    },
    "Button": {
      "name": "Button",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "AsLink",
          "code": "import React from 'react';\nimport { Button } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<Button href=\"https://example.com\" variant=\"primary\">\n  External Link\n</Button>\n<Button href=\"https://example.com\" newTab variant=\"secondary\">\n  Open in New Tab\n</Button>`;\n\nconst AsLink: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Button as Link\">\n            <div className=\"flex flex-wrap gap-4\">\n                <Button href=\"https://example.com\" variant=\"primary\">External Link</Button>\n                <Button href=\"https://example.com\" newTab variant=\"secondary\">Open in New Tab</Button>\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} />\n        </div>\n    </>\n);\n\nexport default AsLink;\n"
        },
        {
          "title": "AsyncAction",
          "code": "import React from 'react';\nimport { Button } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<Button onClick={async () => {\n  await fetch('/api/data');\n}}>\n  Save Data\n</Button>`;\n\nconst AsyncAction: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Automatic Loading State for Async Actions\">\n            <div className=\"flex flex-wrap gap-4\">\n                <Button onClick={async () => {\n                    await new Promise(resolve => setTimeout(resolve, 2000));\n                    alert('Action completed!');\n                }}>\n                    Async Action (Auto Loading)\n                </Button>\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} />\n        </div>\n    </>\n);\n\nexport default AsyncAction;\n"
        },
        {
          "title": "BasicUsage",
          "code": "import React from 'react';\nimport { Button } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { Button } from 'fluxo-ui';\n\n<Button onClick={() => console.log('Clicked!')}>Click me</Button>`;\n\nconst BasicUsage: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Default Button\">\n            <Button onClick={() => alert('Clicked!')}>Click me</Button>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock title=\"Basic Example\" code={code} />\n        </div>\n    </>\n);\n\nexport default BasicUsage;\n"
        },
        {
          "title": "Combinations",
          "code": "import cn from 'classnames';\nimport React from 'react';\nimport { Button } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\n\nconst code = `<Button layout=\"outlined\" variant=\"success\">Outlined Success</Button>\n<Button layout=\"sharp\" variant=\"primary\">Sharp Primary</Button>\n<Button layout=\"rounded\" variant=\"danger\">Rounded Danger</Button>\n<Button layout=\"plain\" variant=\"primary\">Plain Primary</Button>`;\n\nconst layoutLabels = ['default', 'outlined', 'sharp', 'rounded', 'plain'] as const;\nconst variants = ['primary', 'success', 'danger'] as const;\n\nconst Combinations: React.FC = () => {\n    const { isDark } = useStoryTheme();\n\n    return (\n        <>\n            <ComponentDemo title=\"Variants with Different Layouts\">\n                <div className=\"space-y-4\">\n                    {layoutLabels.map(layout => (\n                        <div key={layout} className=\"flex flex-wrap gap-4\">\n                            <span className={cn('w-full text-sm', { 'text-gray-400': isDark, 'text-gray-600': !isDark })}>\n                                {layout.charAt(0).toUpperCase() + layout.slice(1)} Layout:\n                            </span>\n                            {variants.map(variant => (\n                                <Button key={variant} layout={layout} variant={variant}>\n                                    {variant.charAt(0).toUpperCase() + variant.slice(1)}\n                                </Button>\n                            ))}\n                        </div>\n                    ))}\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default Combinations;\n"
        },
        {
          "title": "Confirmation",
          "code": "import React, { useState } from 'react';\nimport { Button } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<Button\n    variant=\"danger\"\n    confirmText=\"Are you sure you want to delete this item? This cannot be undone.\"\n    confirmTitle=\"Delete item\"\n    confirmOkText=\"Delete\"\n    onClick={() => deleteItem()}\n>\n    Delete\n</Button>`;\n\nconst Confirmation: React.FC = () => {\n    const [count, setCount] = useState(0);\n    return (\n        <>\n            <ComponentDemo title=\"Inline Confirmation\" description=\"Use confirmText to show a confirm popover before the click handler runs. The handler only runs after the user clicks the confirm action.\">\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16, alignItems: 'center' }}>\n                    <div className=\"flex flex-wrap gap-4 items-center justify-center\">\n                        <Button\n                            variant=\"danger\"\n                            confirmText=\"Are you sure you want to delete this item? This cannot be undone.\"\n                            confirmTitle=\"Delete item\"\n                            confirmOkText=\"Delete\"\n                            onClick={() => setCount((c) => c + 1)}\n                        >\n                            Delete\n                        </Button>\n                        <Button\n                            variant=\"primary\"\n                            confirmText=\"Submit the form now?\"\n                            confirmTitle=\"Confirm submission\"\n                            onClick={() => setCount((c) => c + 1)}\n                        >\n                            Submit\n                        </Button>\n                    </div>\n                    <div style={{ padding: '10px 14px', background: 'var(--eui-bg-subtle)', border: '1px solid var(--eui-border-subtle)', borderRadius: 6, color: 'var(--eui-text)' }}>\n                        Confirmed actions: <strong>{count}</strong>\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default Confirmation;\n"
        },
        {
          "title": "CountdownTimer",
          "code": "import React from 'react';\nimport { Button } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<Button waitFor={5} variant=\"warning\">\n  Confirm Action\n</Button>`;\n\nconst CountdownTimer: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Button with Countdown (waitFor)\">\n            <div className=\"flex flex-wrap gap-4\">\n                <Button waitFor={5} variant=\"warning\">Confirm Action</Button>\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} />\n        </div>\n    </>\n);\n\nexport default CountdownTimer;\n"
        },
        {
          "title": "FullWidth",
          "code": "import React from 'react';\nimport { Button } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<Button fullWidth>Full Width Button</Button>`;\n\nconst FullWidth: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Full Width Button\" centered={false}>\n            <Button fullWidth>Full Width Button</Button>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} />\n        </div>\n    </>\n);\n\nexport default FullWidth;\n"
        },
        {
          "title": "Layouts",
          "code": "import React from 'react';\nimport { Button } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<Button layout=\"default\" variant=\"primary\">Default</Button>\n<Button layout=\"outlined\" variant=\"primary\">Outlined</Button>\n<Button layout=\"sharp\" variant=\"primary\">Sharp</Button>\n<Button layout=\"rounded\" variant=\"primary\">Rounded</Button>\n<Button layout=\"plain\" variant=\"primary\">Plain</Button>`;\n\nconst Layouts: React.FC = () => (\n    <>\n        <ComponentDemo title=\"All Button Layouts\">\n            <div className=\"flex flex-wrap gap-4\">\n                <Button layout=\"default\" variant=\"primary\">Default</Button>\n                <Button layout=\"outlined\" variant=\"primary\">Outlined</Button>\n                <Button layout=\"sharp\" variant=\"primary\">Sharp</Button>\n                <Button layout=\"rounded\" variant=\"primary\">Rounded</Button>\n                <Button layout=\"plain\" variant=\"primary\">Plain</Button>\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} />\n        </div>\n    </>\n);\n\nexport default Layouts;\n"
        },
        {
          "title": "Sizes",
          "code": "import React from 'react';\nimport { Button } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<Button size=\"xs\">Extra Small</Button>\n<Button size=\"sm\">Small</Button>\n<Button size=\"md\">Medium</Button>\n<Button size=\"lg\">Large</Button>\n<Button size=\"xl\">Extra Large</Button>`;\n\nconst Sizes: React.FC = () => (\n    <>\n        <ComponentDemo title=\"All Button Sizes\">\n            <div className=\"flex flex-wrap items-center gap-4\">\n                <Button size=\"xs\">Extra Small</Button>\n                <Button size=\"sm\">Small</Button>\n                <Button size=\"md\">Medium</Button>\n                <Button size=\"lg\">Large</Button>\n                <Button size=\"xl\">Extra Large</Button>\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} />\n        </div>\n    </>\n);\n\nexport default Sizes;\n"
        },
        {
          "title": "States",
          "code": "import React, { useState } from 'react';\nimport { Button } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<Button>Normal</Button>\n<Button disabled>Disabled</Button>\n<Button isLoading={loading} onClick={handleAsyncAction}>\n  {loading ? 'Loading...' : 'Async Action'}\n</Button>`;\n\nconst States: React.FC = () => {\n    const [loading, setLoading] = useState(false);\n\n    const handleAsyncAction = () => {\n        setLoading(true);\n        setTimeout(() => setLoading(false), 2000);\n    };\n\n    return (\n        <>\n            <ComponentDemo title=\"Button States\">\n                <div className=\"flex flex-wrap gap-4\">\n                    <Button>Normal</Button>\n                    <Button disabled>Disabled</Button>\n                    <Button isLoading={loading} onClick={handleAsyncAction}>\n                        {loading ? 'Loading...' : 'Async Action'}\n                    </Button>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default States;\n"
        },
        {
          "title": "Variants",
          "code": "import React from 'react';\nimport { Button } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<Button variant=\"default\">Default</Button>\n<Button variant=\"primary\">Primary</Button>\n<Button variant=\"secondary\">Secondary</Button>\n<Button variant=\"success\">Success</Button>\n<Button variant=\"warning\">Warning</Button>\n<Button variant=\"danger\">Danger</Button>\n<Button variant=\"info\">Info</Button>`;\n\nconst Variants: React.FC = () => (\n    <>\n        <ComponentDemo title=\"All Button Variants\">\n            <div className=\"flex flex-wrap gap-4\">\n                <Button variant=\"default\">Default</Button>\n                <Button variant=\"primary\">Primary</Button>\n                <Button variant=\"secondary\">Secondary</Button>\n                <Button variant=\"success\">Success</Button>\n                <Button variant=\"warning\">Warning</Button>\n                <Button variant=\"danger\">Danger</Button>\n                <Button variant=\"info\">Info</Button>\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} />\n        </div>\n    </>\n);\n\nexport default Variants;\n"
        },
        {
          "title": "WithIcons",
          "code": "import React from 'react';\nimport { Button } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst plusIcon = (\n    <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" strokeWidth={1.5} stroke=\"currentColor\">\n        <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M12 4.5v15m7.5-7.5h-15\" />\n    </svg>\n);\n\nconst arrowRightIcon = (\n    <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" strokeWidth={1.5} stroke=\"currentColor\">\n        <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M13.5 4.5 21 12m0 0-7.5 7.5M21 12H3\" />\n    </svg>\n);\n\nconst downloadIcon = (\n    <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" strokeWidth={1.5} stroke=\"currentColor\">\n        <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M3 16.5v2.25A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75V16.5M16.5 12 12 16.5m0 0L7.5 12m4.5 4.5V3\" />\n    </svg>\n);\n\nconst code = `<Button leftIcon={<PlusIcon />}>Left Icon</Button>\n<Button rightIcon={<ArrowRightIcon />}>Right Icon</Button>\n<Button leftIcon={<DownloadIcon />} variant=\"success\">Download</Button>`;\n\nconst WithIcons: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Buttons with Icons\">\n            <div className=\"flex flex-wrap gap-4\">\n                <Button leftIcon={plusIcon}>Left Icon</Button>\n                <Button rightIcon={arrowRightIcon}>Right Icon</Button>\n                <Button leftIcon={downloadIcon} variant=\"success\">Download</Button>\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} />\n        </div>\n    </>\n);\n\nexport default WithIcons;\n"
        },
        {
          "title": "WithTooltip",
          "code": "import React from 'react';\nimport { Button } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst trashIcon = (\n    <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" strokeWidth={1.5} stroke=\"currentColor\">\n        <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"m14.74 9-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 0 1-2.244 2.077H8.084a2.25 2.25 0 0 1-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 0 0-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 0 1 3.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 0 0-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 0 0-7.5 0\" />\n    </svg>\n);\n\nconst cogIcon = (\n    <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" strokeWidth={1.5} stroke=\"currentColor\">\n        <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M9.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55 0 1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.325.196.72.257 1.075.124l1.217-.456a1.125 1.125 0 0 1 1.37.49l1.296 2.247a1.125 1.125 0 0 1-.26 1.431l-1.003.827c-.293.241-.438.613-.43.992a7.723 7.723 0 0 1 0 .255c-.008.378.137.75.43.991l1.004.827c.424.35.534.955.26 1.43l-1.298 2.247a1.125 1.125 0 0 1-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.47 6.47 0 0 1-.22.128c-.331.183-.581.495-.644.869l-.213 1.281c-.09.543-.56.94-1.11.94h-2.594c-.55 0-1.019-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52 6.52 0 0 1-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125 1.125 0 0 1-1.369-.49l-1.297-2.247a1.125 1.125 0 0 1 .26-1.431l1.004-.827c.292-.24.437-.613.43-.991a6.932 6.932 0 0 1 0-.255c.007-.38-.138-.751-.43-.992l-1.004-.827a1.125 1.125 0 0 1-.26-1.43l1.297-2.247a1.125 1.125 0 0 1 1.37-.491l1.216.456c.356.133.751.072 1.076-.124.072-.044.146-.086.22-.128.332-.183.582-.495.644-.869l.213-1.28Z\" />\n        <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z\" />\n    </svg>\n);\n\nconst code = `<Button leftIcon={<TrashIcon />} tooltip=\"Delete item\" ariaLabel=\"Delete item\" variant=\"danger\" />\n<Button leftIcon={<CogIcon />} tooltip=\"Open settings\" ariaLabel=\"Settings\" layout=\"plain\" />\n<Button tooltip=\"Saves your work to the cloud\" variant=\"primary\">Save</Button>`;\n\nconst WithTooltip: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Buttons with Tooltips\" description=\"Use the tooltip prop to surface helper text on hover/focus without wrapping the button externally. Especially useful for icon-only buttons where a tooltip is mandatory for accessibility.\">\n            <div className=\"flex flex-wrap gap-4 items-center\">\n                <Button leftIcon={trashIcon} tooltip=\"Delete item\" ariaLabel=\"Delete item\" variant=\"danger\" />\n                <Button leftIcon={cogIcon} tooltip=\"Open settings\" ariaLabel=\"Settings\" layout=\"plain\" />\n                <Button tooltip=\"Saves your work to the cloud\" variant=\"primary\">Save</Button>\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} />\n        </div>\n    </>\n);\n\nexport default WithTooltip;\n"
        }
      ],
      "props": {
        "buttonProps": {
          "variant": {
            "type": "'success' | 'warning' | 'danger' | 'info' | 'default' | 'primary' | 'secondary'",
            "default": "'default'",
            "description": "Button color variant"
          },
          "size": {
            "type": "'xs' | 'sm' | 'md' | 'lg' | 'xl'",
            "default": "'md'",
            "description": "Button size"
          },
          "layout": {
            "type": "'rounded' | 'default' | 'outlined' | 'plain' | 'sharp'",
            "default": "'default'",
            "description": "Button layout style (default: filled with rounded corners, outlined: border with rounded corners, sharp: filled with no radius, plain: no background or border, rounded: fully rounded/pill shape)"
          },
          "disabled": {
            "type": "boolean",
            "default": "false",
            "description": "Disable button interaction"
          },
          "isLoading": {
            "type": "boolean",
            "default": "false",
            "description": "Show loading spinner and disable interaction"
          },
          "leftIcon": {
            "type": "IconComponent | ReactElement",
            "description": "Icon to display on the left side of the button"
          },
          "rightIcon": {
            "type": "IconComponent | ReactElement",
            "description": "Icon to display on the right side of the button"
          },
          "label": {
            "type": "string",
            "description": "Button label text (alternative to children)"
          },
          "children": {
            "type": "ReactNode",
            "description": "Button content"
          },
          "onClick": {
            "type": "(e: MouseEvent) => void | Promise<any>",
            "description": "Click event handler (supports async functions for automatic loading state)"
          },
          "className": {
            "type": "string",
            "description": "Additional CSS classes"
          },
          "loadingMessage": {
            "type": "string",
            "default": "'Loading...'",
            "description": "Message to display while loading (also announced via aria-live for screen readers)"
          },
          "waitFor": {
            "type": "number",
            "description": "Countdown timer in seconds before button becomes clickable"
          },
          "href": {
            "type": "string",
            "description": "URL to navigate to (renders as link)"
          },
          "newTab": {
            "type": "boolean",
            "default": "false",
            "description": "Open link in new tab"
          },
          "type": {
            "type": "'submit' | 'link' | 'button'",
            "default": "'button'",
            "description": "Button type"
          },
          "ariaLabel": {
            "type": "string",
            "description": "Accessibility label"
          },
          "title": {
            "type": "string",
            "description": "HTML title attribute"
          },
          "id": {
            "type": "string",
            "description": "HTML id attribute"
          },
          "fullWidth": {
            "type": "boolean",
            "default": "false",
            "description": "Stretch the button to fill the width of its container (common for modal footers and forms)"
          },
          "tooltip": {
            "type": "ReactNode",
            "description": "Tooltip content shown on hover/focus. Renders the button wrapped in a Tooltip — useful for icon-only buttons where a tooltip is mandatory for accessibility"
          },
          "tooltipPlacement": {
            "type": "'topLeft' | 'topRight' | 'bottomLeft' | 'bottomRight' | 'auto'",
            "default": "'auto'",
            "description": "Placement of the tooltip when tooltip prop is provided"
          },
          "confirmText": {
            "type": "ReactNode",
            "description": "When set, the first click shows a confirm popover; the popover Confirm action runs onClick. Useful for destructive actions"
          },
          "confirmTitle": {
            "type": "string",
            "default": "'Confirm'",
            "description": "Title of the confirm popover when confirmText is set"
          },
          "confirmOkText": {
            "type": "string",
            "default": "'Confirm'",
            "description": "Label of the confirm action button"
          },
          "confirmCancelText": {
            "type": "string",
            "default": "'Cancel'",
            "description": "Label of the cancel action button"
          }
        }
      },
      "storyDir": "button"
    },
    "Checkbox": {
      "name": "Checkbox",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React, { useState } from 'react';\nimport { Checkbox } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { Checkbox } from 'fluxo-ui';\n\nfunction MyComponent() {\n  const [checked, setChecked] = useState(false);\n\n  return (\n    <Checkbox\n      checked={checked}\n      onChange={(e) => setChecked(e.value)}\n      label=\"I agree to the terms and conditions\"\n    />\n  );\n}`;\n\nconst BasicUsage: React.FC = () => {\n    const [basicChecked, setBasicChecked] = useState(false);\n\n    return (\n        <>\n            <ComponentDemo title=\"Basic Checkbox\">\n                <div className=\"space-y-4\">\n                    <Checkbox\n                        checked={basicChecked}\n                        onChange={(e) => setBasicChecked(e.value)}\n                        label=\"I agree to the terms and conditions\"\n                    />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock title=\"Basic Example\" code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "CheckboxGroup",
          "code": "import React, { useState } from 'react';\nimport { Checkbox } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `const [values, setValues] = useState({\n  option1: true,\n  option2: false,\n  option3: true\n});\n\nconst handleChange = (key) => (e) => {\n  setValues(prev => ({\n    ...prev,\n    [key]: e.value\n  }));\n};\n\n<Checkbox\n  checked={values.option1}\n  onChange={handleChange('option1')}\n  label=\"Option 1\"\n/>\n<Checkbox\n  checked={values.option2}\n  onChange={handleChange('option2')}\n  label=\"Option 2\"\n/>\n<Checkbox\n  checked={values.option3}\n  onChange={handleChange('option3')}\n  label=\"Option 3\"\n/>`;\n\nconst CheckboxGroup: React.FC = () => {\n    const [groupValues, setGroupValues] = useState({\n        option1: true,\n        option2: false,\n        option3: true,\n    });\n\n    const handleGroupChange = (key: string) => (e: any) => {\n        setGroupValues((prev) => ({\n            ...prev,\n            [key]: e.value,\n        }));\n    };\n\n    return (\n        <>\n            <ComponentDemo title=\"Multiple Checkboxes\">\n                <div className=\"space-y-3\">\n                    <Checkbox checked={groupValues.option1} onChange={handleGroupChange('option1')} label=\"Option 1\" />\n                    <Checkbox checked={groupValues.option2} onChange={handleGroupChange('option2')} label=\"Option 2\" />\n                    <Checkbox checked={groupValues.option3} onChange={handleGroupChange('option3')} label=\"Option 3\" />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default CheckboxGroup;\n"
        },
        {
          "title": "IndeterminateState",
          "code": "import React from 'react';\nimport { Checkbox } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<Checkbox indeterminate label=\"Select All\" />\n<div className=\"ml-6 space-y-2\">\n  <Checkbox label=\"Item 1\" checked={true} onChange={handleChange} />\n  <Checkbox label=\"Item 2\" checked={false} onChange={handleChange} />\n  <Checkbox label=\"Item 3\" checked={true} onChange={handleChange} />\n</div>`;\n\nconst IndeterminateState: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo title=\"Indeterminate Checkbox\">\n                <div className=\"space-y-3\">\n                    <Checkbox indeterminate label=\"Select All\" />\n                    <div className=\"ml-6 space-y-2\">\n                        <Checkbox label=\"Item 1\" checked={true} onChange={() => {}} />\n                        <Checkbox label=\"Item 2\" checked={false} onChange={() => {}} />\n                        <Checkbox label=\"Item 3\" checked={true} onChange={() => {}} />\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default IndeterminateState;\n"
        },
        {
          "title": "States",
          "code": "import React from 'react';\nimport { Checkbox } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<Checkbox label=\"Normal checkbox\" checked={false} onChange={handleChange} />\n<Checkbox label=\"Checked checkbox\" checked={true} onChange={handleChange} />\n<Checkbox label=\"Disabled unchecked\" disabled checked={false} onChange={handleChange} />\n<Checkbox label=\"Disabled checked\" disabled checked={true} onChange={handleChange} />\n<Checkbox label=\"Required checkbox\" required />\n<Checkbox label=\"Indeterminate\" indeterminate />`;\n\nconst States: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo title=\"Checkbox States\">\n                <div className=\"space-y-4\">\n                    <Checkbox label=\"Normal checkbox\" checked={false} onChange={() => {}} />\n                    <Checkbox label=\"Checked checkbox\" checked={true} onChange={() => {}} />\n                    <Checkbox label=\"Disabled unchecked\" disabled checked={false} onChange={() => {}} />\n                    <Checkbox label=\"Disabled checked\" disabled checked={true} onChange={() => {}} />\n                    <Checkbox label=\"Required checkbox\" required checked={false} onChange={() => {}} />\n                    <Checkbox label=\"Indeterminate\" indeterminate />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default States;\n"
        }
      ],
      "props": {
        "checkboxProps": {
          "checked": {
            "type": "boolean",
            "description": "Whether the checkbox is checked (controlled component)"
          },
          "indeterminate": {
            "type": "boolean",
            "default": "false",
            "description": "Show indeterminate state (partially selected). Sets aria-checked='mixed' and the native indeterminate flag for SR users"
          },
          "size": {
            "type": "'xs' | 'sm' | 'md' | 'lg' | 'xl'",
            "default": "'md'",
            "description": "Checkbox size"
          },
          "disabled": {
            "type": "boolean",
            "default": "false",
            "description": "Disable the checkbox"
          },
          "required": {
            "type": "boolean",
            "default": "false",
            "description": "Mark the checkbox as required"
          },
          "label": {
            "type": "string",
            "description": "Label text displayed next to the checkbox"
          },
          "onChange": {
            "type": "(event: ComponentEvent<boolean>) => void",
            "description": "Change event handler. Receives event object with value, name, and args properties"
          },
          "id": {
            "type": "string",
            "description": "HTML id attribute for the checkbox input"
          },
          "name": {
            "type": "string",
            "description": "Name attribute for the checkbox input (used in forms)"
          },
          "args": {
            "type": "any",
            "description": "Additional arguments passed to onChange handler"
          },
          "className": {
            "type": "string",
            "description": "Additional CSS classes for the container"
          }
        }
      },
      "storyDir": "checkbox"
    },
    "Chips": {
      "name": "Chips",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React, { useState } from 'react';\nimport { Chips } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { basicUsageCode } from './chips-story-data';\n\nconst BasicUsage: React.FC = () => {\n    const [basicChips, setBasicChips] = useState(['React', 'TypeScript']);\n    const [customChips, setCustomChips] = useState(['Apple', 'Banana', 'Cherry']);\n\n    return (\n        <>\n            <div className=\"grid gap-8\">\n                <ComponentDemo title=\"Basic Chips\" description=\"Simple chips with add and remove functionality\">\n                    <div className=\"w-full max-w-96\">\n                        <Chips value={basicChips} placeholder=\"Add programming languages...\" onChange={(e) => setBasicChips(e.value)} />\n                    </div>\n                </ComponentDemo>\n\n                <ComponentDemo title=\"Fruit Tags\" description=\"Chips with custom placeholder and preset values\">\n                    <div className=\"w-full max-w-96\">\n                        <Chips value={customChips} placeholder=\"Add fruits...\" onChange={(e) => setCustomChips(e.value)} />\n                    </div>\n                </ComponentDemo>\n            </div>\n\n            <div className=\"mt-4\">\n                <CodeBlock code={basicUsageCode} language=\"typescript\" />\n            </div>\n        </>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "LimitedChips",
          "code": "import React from 'react';\nimport { Chips } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { advancedUsageCode } from './chips-story-data';\n\nconst LimitedChips: React.FC = () => {\n    return (\n        <>\n            <div className=\"grid gap-8\">\n                <ComponentDemo title=\"Limited Chips\" description=\"Maximum 3 chips allowed\">\n                    <div className=\"w-full max-w-96\">\n                        <Chips value={[]} placeholder=\"Max 3 items...\" maxItems={3} onChange={(e) => console.log('Changed:', e.value)} />\n                    </div>\n                </ComponentDemo>\n\n                <ComponentDemo title=\"Non-removable Chips\" description=\"Chips that cannot be removed\">\n                    <div className=\"w-full max-w-96\">\n                        <Chips\n                            value={['Fixed', 'Tags', 'Here']}\n                            placeholder=\"Add more (but can't remove existing)...\"\n                            onChange={(e) => console.log('Changed:', e.value)}\n                        />\n                    </div>\n                </ComponentDemo>\n            </div>\n\n            <div className=\"mt-4\">\n                <CodeBlock code={advancedUsageCode} language=\"typescript\" />\n            </div>\n        </>\n    );\n};\n\nexport default LimitedChips;\n"
        },
        {
          "title": "States",
          "code": "import React from 'react';\nimport { Chips } from '../../../components';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst States: React.FC = () => {\n    return (\n        <ComponentDemo title=\"Disabled State\" description=\"Chips in disabled state\">\n            <div className=\"w-full max-w-96\">\n                <Chips value={['Disabled', 'Chips']} disabled />\n            </div>\n        </ComponentDemo>\n    );\n};\n\nexport default States;\n"
        }
      ],
      "props": {
        "chipsProps": {
          "value": {
            "type": "string[]",
            "default": "[]",
            "description": "Array of chip values"
          },
          "onChange": {
            "type": "function",
            "description": "Callback fired when chips change: (event: ComponentEvent<string[]>) => void"
          },
          "placeholder": {
            "type": "string",
            "default": "\"Type and press Enter to add\"",
            "description": "Placeholder text for input"
          },
          "maxItems": {
            "type": "number",
            "description": "Maximum number of chips allowed"
          },
          "allowDuplicates": {
            "type": "boolean",
            "default": false,
            "description": "Whether duplicate chips are allowed"
          },
          "separator": {
            "type": "string",
            "default": "\",\"",
            "description": "Separator character for adding multiple chips at once"
          },
          "disabled": {
            "type": "boolean",
            "default": false,
            "description": "Whether the component is disabled"
          },
          "readonly": {
            "type": "boolean",
            "default": false,
            "description": "Whether the component is readonly (no input or removal allowed)"
          },
          "id": {
            "type": "string",
            "description": "HTML id attribute for the container"
          },
          "name": {
            "type": "string",
            "description": "HTML name attribute for the hidden input"
          },
          "args": {
            "type": "any",
            "description": "Custom arguments passed to onChange callback"
          },
          "ariaLabel": {
            "type": "string",
            "description": "Accessible label for the chip list and input"
          },
          "commitOnTab": {
            "type": "boolean",
            "default": true,
            "description": "Commit the current input as a chip when Tab is pressed (common tag-input UX)"
          }
        }
      },
      "storyDir": "chips"
    },
    "DeferredView": {
      "name": "DeferredView",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsageDemo",
          "code": "import React, { useState } from 'react';\nimport { DeferredView } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst HeavyComponent: React.FC<{ label: string }> = ({ label }) => {\n    return (\n        <div className=\"p-6 rounded-lg border border-emerald-400/30 bg-emerald-500/10\">\n            <div className=\"text-lg font-semibold text-emerald-400 mb-2\">{label} - Loaded!</div>\n            <p className=\"text-sm opacity-70\">This component was deferred until it became visible in the viewport.</p>\n        </div>\n    );\n};\n\nconst BasicUsageDemo: React.FC = () => {\n    const [mountLog, setMountLog] = useState<string[]>([]);\n\n    const logMount = (name: string) => {\n        setMountLog((prev) => [...prev, `${name} mounted at ${new Date().toLocaleTimeString()}`]);\n    };\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Scroll to reveal\"\n                description=\"Scroll down within this container to see components mount only when they enter the viewport. Each card logs when it was mounted.\"\n            >\n                <div className=\"w-full space-y-4\">\n                    {mountLog.length > 0 && (\n                        <div className=\"p-3 rounded-lg bg-gray-900/50 border border-gray-700 text-xs font-mono max-h-32 overflow-y-auto\">\n                            {mountLog.map((log, i) => (\n                                <div key={i} className=\"text-gray-300 py-0.5\">\n                                    {log}\n                                </div>\n                            ))}\n                        </div>\n                    )}\n                    <div className=\"h-64 overflow-y-auto rounded-lg border border-gray-700 p-4 space-y-96\">\n                        <div className=\"text-center text-sm opacity-50 py-4\">Scroll down to load deferred components...</div>\n                        <DeferredView>\n                            <MountTracker name=\"Component A\" onMount={logMount} />\n                        </DeferredView>\n                        <DeferredView>\n                            <MountTracker name=\"Component B\" onMount={logMount} />\n                        </DeferredView>\n                        <DeferredView>\n                            <MountTracker name=\"Component C\" onMount={logMount} />\n                        </DeferredView>\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock\n                    code={`import { DeferredView } from 'fluxo-ui';\n\n<DeferredView>\n  <ExpensiveComponent />\n</DeferredView>\n\n<DeferredView>\n  <AnotherExpensiveComponent />\n</DeferredView>`}\n                />\n            </div>\n        </>\n    );\n};\n\nconst MountTracker: React.FC<{ name: string; onMount: (name: string) => void }> = ({ name, onMount }) => {\n    const hasLogged = React.useRef(false);\n    React.useEffect(() => {\n        if (!hasLogged.current) {\n            hasLogged.current = true;\n            onMount(name);\n        }\n    }, [name, onMount]);\n\n    return <HeavyComponent label={name} />;\n};\n\nexport default BasicUsageDemo;\n"
        },
        {
          "title": "KeepMountedDemo",
          "code": "import React, { useEffect, useState } from 'react';\nimport { DeferredView } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst CounterComponent: React.FC<{ label: string }> = ({ label }) => {\n    const [count, setCount] = useState(0);\n\n    useEffect(() => {\n        const timerRef = setInterval(() => {\n            setCount((c) => c + 1);\n        }, 1000);\n        return () => clearInterval(timerRef);\n    }, []);\n\n    return (\n        <div className=\"p-4 rounded-lg border border-amber-400/30 bg-amber-500/10\">\n            <div className=\"font-semibold text-amber-400\">{label}</div>\n            <div className=\"text-2xl font-mono mt-1\">{count}s</div>\n        </div>\n    );\n};\n\nconst KeepMountedDemo: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo\n                title=\"keepMounted vs unmount on leave\"\n                description=\"With keepMounted (default), once a component mounts it stays mounted even when scrolled out of view. Set keepMounted={false} to unmount when leaving the viewport — the counter resets each time.\"\n            >\n                <div className=\"w-full grid grid-cols-1 md:grid-cols-2 gap-4\">\n                    <div>\n                        <div className=\"text-sm font-medium mb-2 opacity-70\">keepMounted=true (default)</div>\n                        <div className=\"h-48 overflow-y-auto rounded-lg border border-gray-700 p-4 space-y-96\">\n                            <div className=\"text-xs opacity-50 text-center\">Scroll down, then back up — counter keeps running</div>\n                            <DeferredView keepMounted>\n                                <CounterComponent label=\"Persistent Counter\" />\n                            </DeferredView>\n                        </div>\n                    </div>\n                    <div>\n                        <div className=\"text-sm font-medium mb-2 opacity-70\">keepMounted=false</div>\n                        <div className=\"h-48 overflow-y-auto rounded-lg border border-gray-700 p-4 space-y-96\">\n                            <div className=\"text-xs opacity-50 text-center\">Scroll down, then back up — counter resets</div>\n                            <DeferredView keepMounted={false}>\n                                <CounterComponent label=\"Resetting Counter\" />\n                            </DeferredView>\n                        </div>\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock\n                    code={`// Default: stays mounted once visible\n<DeferredView keepMounted>\n  <StatefulComponent />\n</DeferredView>\n\n// Unmounts when scrolled out of view\n<DeferredView keepMounted={false}>\n  <StatefulComponent />\n</DeferredView>`}\n                />\n            </div>\n        </>\n    );\n};\n\nexport default KeepMountedDemo;\n"
        },
        {
          "title": "LazyImageDemo",
          "code": "import React, { useEffect, useState } from 'react';\nimport { DeferredView, ShimmerDiv } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst imageUrls = [\n    'https://picsum.photos/seed/defer1/400/250',\n    'https://picsum.photos/seed/defer2/400/250',\n    'https://picsum.photos/seed/defer3/400/250',\n    'https://picsum.photos/seed/defer4/400/250',\n    'https://picsum.photos/seed/defer5/400/250',\n    'https://picsum.photos/seed/defer6/400/250',\n];\n\nconst DeferredImage: React.FC<{ src: string; index: number }> = ({ src, index }) => {\n    const [loaded, setLoaded] = useState(false);\n\n    useEffect(() => {\n        const img = new Image();\n        img.onload = () => setLoaded(true);\n        img.src = src;\n    }, [src]);\n\n    return (\n        <div className=\"rounded-lg overflow-hidden border border-gray-700\">\n            {!loaded ? (\n                <ShimmerDiv style={{ height: 160, width: '100%' }} />\n            ) : (\n                <img src={src} alt={`Deferred image ${index + 1}`} className=\"w-full h-40 object-cover\" />\n            )}\n            <div className=\"p-2 text-xs opacity-60 text-center\">Image {index + 1}</div>\n        </div>\n    );\n};\n\nconst imagePlaceholder = <ShimmerDiv style={{ height: 185, width: '100%', borderRadius: 8 }} />;\n\nconst LazyImageDemo: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo\n                title=\"Lazy image gallery\"\n                description=\"Images are not fetched until their container enters the viewport. This is ideal for long pages with many images.\"\n            >\n                <div className=\"h-72 overflow-y-auto rounded-lg border border-gray-700 p-4 w-full\">\n                    <div className=\"grid grid-cols-2 gap-4\">\n                        {imageUrls.map((url, i) => (\n                            <DeferredView key={url} placeholder={imagePlaceholder} rootMargin=\"50px\">\n                                <DeferredImage src={url} index={i} />\n                            </DeferredView>\n                        ))}\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock\n                    code={`import { DeferredView, ShimmerDiv } from 'fluxo-ui';\n\nconst placeholder = <ShimmerDiv style={{ height: 185, width: '100%' }} />;\n\n{images.map((url) => (\n  <DeferredView key={url} placeholder={placeholder} rootMargin=\"50px\">\n    <img src={url} alt=\"Lazy loaded\" />\n  </DeferredView>\n))}`}\n                />\n            </div>\n        </>\n    );\n};\n\nexport default LazyImageDemo;\n"
        },
        {
          "title": "PlaceholderDemo",
          "code": "import React from 'react';\nimport { DeferredView, ShimmerDiv } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst LoadedCard: React.FC = () => {\n    return (\n        <div className=\"p-6 rounded-lg border border-blue-400/30 bg-blue-500/10\">\n            <div className=\"text-lg font-semibold text-blue-400 mb-2\">Content Loaded</div>\n            <p className=\"text-sm opacity-70\">This card replaced the shimmer placeholder when it entered the viewport.</p>\n        </div>\n    );\n};\n\nconst shimmerPlaceholder = (\n    <div className=\"space-y-3 p-6 rounded-lg border border-gray-700\">\n        <ShimmerDiv style={{ height: 20, width: '40%', borderRadius: 4 }} />\n        <ShimmerDiv style={{ height: 14, width: '80%', borderRadius: 4 }} />\n        <ShimmerDiv style={{ height: 14, width: '60%', borderRadius: 4 }} />\n    </div>\n);\n\nconst PlaceholderDemo: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo\n                title=\"Custom placeholder\"\n                description=\"Use the placeholder prop to show a shimmer skeleton or any custom loading UI while the real content is deferred.\"\n            >\n                <div className=\"h-64 overflow-y-auto rounded-lg border border-gray-700 p-4 space-y-96 w-full\">\n                    <div className=\"text-center text-sm opacity-50 py-4\">Scroll down to see the shimmer replaced by real content...</div>\n                    <DeferredView placeholder={shimmerPlaceholder}>\n                        <LoadedCard />\n                    </DeferredView>\n                    <DeferredView placeholder={shimmerPlaceholder}>\n                        <LoadedCard />\n                    </DeferredView>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock\n                    code={`import { DeferredView, ShimmerDiv } from 'fluxo-ui';\n\nconst placeholder = (\n  <div className=\"space-y-3 p-6\">\n    <ShimmerDiv style={{ height: 20, width: '40%', borderRadius: 4 }} />\n    <ShimmerDiv style={{ height: 14, width: '80%', borderRadius: 4 }} />\n  </div>\n);\n\n<DeferredView placeholder={placeholder}>\n  <ExpensiveComponent />\n</DeferredView>`}\n                />\n            </div>\n        </>\n    );\n};\n\nexport default PlaceholderDemo;\n"
        },
        {
          "title": "RootMarginDemo",
          "code": "import React, { useState } from 'react';\nimport { DeferredView } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst RootMarginDemo: React.FC = () => {\n    const [loaded, setLoaded] = useState<string[]>([]);\n\n    const trackLoad = (id: string) => {\n        setLoaded((prev) => (prev.includes(id) ? prev : [...prev, id]));\n    };\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Root margin for preloading\"\n                description='Use rootMargin to start loading content before it enters the viewport. With rootMargin=\"200px\", components begin mounting 200px before they scroll into view.'\n            >\n                <div className=\"w-full space-y-4\">\n                    <div className=\"text-sm opacity-70\">\n                        Loaded: {loaded.length === 0 ? 'None yet' : loaded.join(', ')}\n                    </div>\n                    <div className=\"h-64 overflow-y-auto rounded-lg border border-gray-700 p-4 space-y-96\">\n                        <div className=\"text-center text-sm opacity-50 py-4\">Components below load 200px before they enter the visible area</div>\n                        {['Card A', 'Card B', 'Card C'].map((name) => (\n                            <DeferredView key={name} rootMargin=\"200px\">\n                                <PreloadTracker name={name} onLoad={trackLoad} />\n                            </DeferredView>\n                        ))}\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock\n                    code={`// Preload 200px before entering viewport\n<DeferredView rootMargin=\"200px\">\n  <HeavyComponent />\n</DeferredView>\n\n// Preload 50% of viewport height ahead\n<DeferredView rootMargin=\"50%\">\n  <HeavyComponent />\n</DeferredView>`}\n                />\n            </div>\n        </>\n    );\n};\n\nconst PreloadTracker: React.FC<{ name: string; onLoad: (name: string) => void }> = ({ name, onLoad }) => {\n    const hasLogged = React.useRef(false);\n    React.useEffect(() => {\n        if (!hasLogged.current) {\n            hasLogged.current = true;\n            onLoad(name);\n        }\n    }, [name, onLoad]);\n\n    return (\n        <div className=\"p-4 rounded-lg border border-purple-400/30 bg-purple-500/10\">\n            <div className=\"font-semibold text-purple-400\">{name} — Preloaded</div>\n            <p className=\"text-sm opacity-70 mt-1\">This loaded before it was visible thanks to rootMargin.</p>\n        </div>\n    );\n};\n\nexport default RootMarginDemo;\n"
        }
      ],
      "props": {
        "deferredViewProps": {
          "children": {
            "type": "ReactNode",
            "description": "Content to render once the component enters the viewport."
          },
          "placeholder": {
            "type": "ReactNode",
            "default": "empty div",
            "description": "Content to show while the children are deferred. Use a shimmer skeleton, spinner, or any custom placeholder."
          },
          "rootMargin": {
            "type": "string",
            "default": "\"0px\"",
            "description": "Margin around the root (viewport) for the IntersectionObserver. Use positive values to preload content before it enters the viewport (e.g. \"200px\")."
          },
          "threshold": {
            "type": "number",
            "default": "0",
            "description": "Percentage of the element that must be visible before mounting (0 to 1). 0 means any pixel visible triggers mount."
          },
          "keepMounted": {
            "type": "boolean",
            "default": "true",
            "description": "When true, children stay mounted after first visibility. When false, children unmount when scrolled out of view."
          },
          "className": {
            "type": "string",
            "description": "Additional CSS classes applied to the wrapper element."
          },
          "style": {
            "type": "CSSProperties",
            "description": "Inline styles applied to the wrapper element."
          }
        }
      },
      "storyDir": "deferred-view"
    },
    "Dropdown": {
      "name": "Dropdown",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React, { useState } from 'react';\nimport { Dropdown as DropdownRaw } from '../../../components';\nimport { withFieldLabel } from '../../../utils/field-label';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { basicOptions } from './dropdown-story-data';\n\nconst Dropdown = withFieldLabel(DropdownRaw);\n\nconst code = `import { Dropdown } from 'fluxo-ui';\n\nfunction MyComponent() {\n  const [value, setValue] = useState('');\n\n  const options = [\n    { label: 'Option 1', value: 'option1' },\n    { label: 'Option 2', value: 'option2' },\n    { label: 'Option 3', value: 'option3' },\n    { label: 'Disabled Option', value: 'disabled', disabled: true }\n  ];\n\n  return (\n    <Dropdown\n      label=\"Select an option\"\n      placeholder=\"Choose one...\"\n      options={options}\n      value={value}\n      onChange={setValue}\n    />\n  );\n}`;\n\nconst BasicUsage: React.FC = () => {\n    const [basicValue, setBasicValue] = useState('');\n\n    return (\n        <>\n            <ComponentDemo title=\"Basic Dropdown\">\n                <div className=\"w-full max-w-sm\">\n                    <Dropdown\n                        label=\"Select an option\"\n                        placeholder=\"Choose one...\"\n                        options={basicOptions}\n                        value={basicValue}\n                        onChange={(e) => setBasicValue(e.value)}\n                    />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock title=\"Basic Example\" code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "ClearableDropdown",
          "code": "import React, { useState } from 'react';\nimport { Dropdown as DropdownRaw } from '../../../components';\nimport { withFieldLabel } from '../../../utils/field-label';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { countryOptions } from './dropdown-story-data';\n\nconst Dropdown = withFieldLabel(DropdownRaw);\n\nconst code = `<Dropdown\n  label=\"Country\"\n  options={countryOptions}\n  value={value}\n  onChange={setValue}\n  showClear\n/>`;\n\nconst ClearableDropdown: React.FC = () => {\n    const [clearableValue, setClearableValue] = useState('option2');\n\n    return (\n        <>\n            <ComponentDemo title=\"Dropdown with Clear Button\">\n                <div className=\"w-full max-w-sm\">\n                    <Dropdown\n                        label=\"Country\"\n                        options={countryOptions}\n                        value={clearableValue}\n                        onChange={(e) => setClearableValue(e.value)}\n                        showClear\n                    />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default ClearableDropdown;\n"
        },
        {
          "title": "CustomFieldMapping",
          "code": "import React, { useState } from 'react';\nimport { Dropdown as DropdownRaw } from '../../../components';\nimport { withFieldLabel } from '../../../utils/field-label';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { customFieldOptions } from './dropdown-story-data';\n\nconst Dropdown = withFieldLabel(DropdownRaw);\n\nconst code = `const countries = [\n  { name: 'United States', code: 'US' },\n  { name: 'Canada', code: 'CA' },\n  { name: 'United Kingdom', code: 'UK' },\n  { name: 'Germany', code: 'DE' },\n];\n\n<Dropdown\n  label=\"Country\"\n  placeholder=\"Select a country...\"\n  options={countries}\n  optionLabel=\"name\"\n  optionValue=\"code\"\n  value={value}\n  onChange={setValue}\n/>`;\n\nconst CustomFieldMapping: React.FC = () => {\n    const [customFieldValue, setCustomFieldValue] = useState('');\n\n    return (\n        <>\n            <ComponentDemo title=\"Dropdown with optionLabel / optionValue\">\n                <div className=\"w-full max-w-sm\">\n                    <Dropdown\n                        label=\"Country\"\n                        placeholder=\"Select a country...\"\n                        options={customFieldOptions}\n                        optionLabel=\"name\"\n                        optionValue=\"code\"\n                        value={customFieldValue}\n                        onChange={(e) => setCustomFieldValue(e.value)}\n                    />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default CustomFieldMapping;\n"
        },
        {
          "title": "DropdownStates",
          "code": "import React from 'react';\nimport { Dropdown as DropdownRaw } from '../../../components';\nimport { withFieldLabel } from '../../../utils/field-label';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { basicOptions } from './dropdown-story-data';\n\nconst Dropdown = withFieldLabel(DropdownRaw);\n\nconst code = `<Dropdown label=\"Normal\" placeholder=\"Normal state\" options={options} />\n<Dropdown label=\"Selected\" options={options} value=\"option2\" onChange={setValue} />\n<Dropdown label=\"Disabled\" placeholder=\"Disabled state\" options={options} disabled />\n<Dropdown label=\"Read Only\" options={options} value=\"option1\" readonly />\n<Dropdown label=\"Required\" placeholder=\"Required field\" options={options} required />\n<Dropdown label=\"With Error\" options={options} error=\"This field is required\" />`;\n\nconst DropdownStates: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo title=\"Dropdown States\">\n                <div className=\"w-full max-w-sm space-y-4\">\n                    <Dropdown label=\"Normal\" placeholder=\"Normal state\" options={basicOptions} />\n                    <Dropdown label=\"Selected\" options={basicOptions} value=\"option2\" />\n                    <Dropdown label=\"Disabled\" placeholder=\"Disabled state\" options={basicOptions} disabled />\n                    <Dropdown label=\"Read Only\" options={basicOptions} value=\"option1\" readOnly />\n                    <Dropdown label=\"Required\" placeholder=\"Required field\" options={basicOptions} required />\n                    <Dropdown label=\"With Error\" placeholder=\"Select an option\" options={basicOptions} error=\"This field is required\" />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default DropdownStates;\n"
        },
        {
          "title": "GroupedOptions",
          "code": "import React, { useState } from 'react';\nimport { Dropdown as DropdownRaw } from '../../../components';\nimport { withFieldLabel } from '../../../utils/field-label';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { groupedOptions } from './dropdown-story-data';\n\nconst Dropdown = withFieldLabel(DropdownRaw);\n\nconst code = `const groupedOptions = [\n  {\n    label: 'Frontend',\n    items: [\n      { label: 'React', value: 'react' },\n      { label: 'Vue.js', value: 'vue' },\n      { label: 'Angular', value: 'angular' },\n    ],\n  },\n  {\n    label: 'Backend',\n    items: [\n      { label: 'Node.js', value: 'nodejs' },\n      { label: 'Django', value: 'django' },\n    ],\n  },\n];\n\n<Dropdown\n  label=\"Technology\"\n  placeholder=\"Select a technology...\"\n  options={groupedOptions}\n  value={value}\n  onChange={setValue}\n  searchable\n/>`;\n\nconst GroupedOptions: React.FC = () => {\n    const [groupedValue, setGroupedValue] = useState('');\n\n    return (\n        <>\n            <ComponentDemo title=\"Dropdown with Grouped Items\">\n                <div className=\"w-full max-w-sm\">\n                    <Dropdown\n                        label=\"Technology\"\n                        placeholder=\"Select a technology...\"\n                        options={groupedOptions}\n                        value={groupedValue}\n                        onChange={(e) => setGroupedValue(e.value)}\n                        searchable\n                    />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default GroupedOptions;\n"
        },
        {
          "title": "SearchableDropdown",
          "code": "import React, { useState } from 'react';\nimport { Dropdown as DropdownRaw } from '../../../components';\nimport { withFieldLabel } from '../../../utils/field-label';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { frameworkOptions } from './dropdown-story-data';\n\nconst Dropdown = withFieldLabel(DropdownRaw);\n\nconst code = `const frameworkOptions = [\n  { label: 'React', value: 'react' },\n  { label: 'Vue.js', value: 'vue' },\n  { label: 'Angular', value: 'angular' },\n  { label: 'Svelte', value: 'svelte' },\n  // ... more options\n];\n\n<Dropdown\n  label=\"Frontend Framework\"\n  placeholder=\"Search frameworks...\"\n  options={frameworkOptions}\n  value={value}\n  onChange={setValue}\n  searchable\n/>`;\n\nconst SearchableDropdown: React.FC = () => {\n    const [searchableValue, setSearchableValue] = useState('react');\n\n    return (\n        <>\n            <ComponentDemo title=\"Dropdown with Search\">\n                <div className=\"w-full max-w-sm\">\n                    <Dropdown\n                        label=\"Frontend Framework\"\n                        placeholder=\"Search frameworks...\"\n                        options={frameworkOptions}\n                        value={searchableValue}\n                        onChange={(e) => setSearchableValue(e.value)}\n                        searchable\n                    />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default SearchableDropdown;\n"
        }
      ],
      "props": {
        "dropdownProps": {
          "value": {
            "type": "any",
            "description": "Currently selected value (controlled component)"
          },
          "options": {
            "type": "ListItem[] | ListItemGroup[]",
            "required": true,
            "description": "Flat array of items or grouped items. Each group has a label, optional icon, and an items array."
          },
          "onChange": {
            "type": "function",
            "description": "Change event handler called with {event, value, name, args}"
          },
          "placeholder": {
            "type": "string",
            "description": "Placeholder text when no option is selected"
          },
          "label": {
            "type": "string",
            "description": "Label text for the dropdown"
          },
          "error": {
            "type": "string",
            "description": "Error message to display"
          },
          "disabled": {
            "type": "boolean",
            "default": false,
            "description": "Disable the dropdown"
          },
          "readonly": {
            "type": "boolean",
            "default": false,
            "description": "Make the dropdown read-only"
          },
          "required": {
            "type": "boolean",
            "default": false,
            "description": "Mark the dropdown as required"
          },
          "searchable": {
            "type": "boolean",
            "default": false,
            "description": "Enable search/filter functionality"
          },
          "loading": {
            "type": "boolean",
            "default": false,
            "description": "Show loading state"
          },
          "emptyMessage": {
            "type": "string",
            "default": "No options available",
            "description": "Message to display when no options are available"
          },
          "showClear": {
            "type": "boolean",
            "default": false,
            "description": "Show clear button to deselect"
          },
          "renderItem": {
            "type": "function",
            "description": "Custom render function for dropdown items: (item, index, isSelected, isHighlighted) => ReactNode"
          },
          "renderValue": {
            "type": "function",
            "description": "Custom render function for selected value: (item) => ReactNode"
          },
          "id": {
            "type": "string",
            "description": "HTML id attribute for the input element"
          },
          "name": {
            "type": "string",
            "description": "HTML name attribute for form submission"
          },
          "args": {
            "type": "any",
            "description": "Custom arguments passed to onChange event"
          },
          "optionLabel": {
            "type": "string",
            "default": "label",
            "description": "Property name to use as the display label from each option object"
          },
          "optionValue": {
            "type": "string",
            "default": "value",
            "description": "Property name to use as the value from each option object"
          },
          "className": {
            "type": "string",
            "description": "Additional CSS classes"
          }
        }
      },
      "storyDir": "dropdown"
    },
    "Fab": {
      "name": "Fab",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {
        "fabProps": {
          "icon": {
            "type": "IconComponent | ReactElement",
            "description": "Icon displayed in the button",
            "default": "-"
          },
          "label": {
            "type": "string",
            "description": "Label text (visible in extended mode)"
          },
          "variant": {
            "type": "'default' | 'primary' | 'success' | 'warning' | 'danger' | 'info' | 'secondary'",
            "default": "'primary'",
            "description": "Color variant"
          },
          "size": {
            "type": "'xs' | 'sm' | 'md' | 'lg' | 'xl'",
            "default": "'md'",
            "description": "Button size"
          },
          "position": {
            "type": "'bottom-right' | 'bottom-left' | 'top-right' | 'top-left' | 'bottom-center' | 'top-center'",
            "default": "'bottom-right'",
            "description": "Fixed position on screen (when fixed=true)"
          },
          "fixed": {
            "type": "boolean",
            "default": "false",
            "description": "Use fixed positioning on screen"
          },
          "extended": {
            "type": "boolean",
            "default": "false",
            "description": "Show label text alongside icon"
          },
          "disabled": {
            "type": "boolean",
            "default": "false",
            "description": "Disable the button"
          },
          "onClick": {
            "type": "(e: MouseEvent) => void",
            "description": "Click handler"
          },
          "className": {
            "type": "string",
            "description": "Additional CSS class"
          },
          "ariaLabel": {
            "type": "string",
            "description": "Accessible label"
          },
          "id": {
            "type": "string",
            "description": "HTML id attribute"
          },
          "title": {
            "type": "string",
            "description": "Tooltip text"
          }
        },
        "speedDialProps": {
          "icon": {
            "type": "IconComponent | ReactElement",
            "description": "Custom icon for the trigger (default: plus)"
          },
          "openIcon": {
            "type": "IconComponent | ReactElement",
            "description": "Icon shown when open (default: close/X)"
          },
          "items": {
            "type": "SpeedDialItem[]",
            "description": "Array of action items with icon, label, variant, onClick",
            "default": "-"
          },
          "variant": {
            "type": "'default' | 'primary' | 'success' | 'warning' | 'danger' | 'info' | 'secondary'",
            "default": "'primary'",
            "description": "Trigger button color variant"
          },
          "size": {
            "type": "'xs' | 'sm' | 'md' | 'lg' | 'xl'",
            "default": "'md'",
            "description": "Overall size"
          },
          "position": {
            "type": "'bottom-right' | 'bottom-left' | 'top-right' | 'top-left' | 'bottom-center' | 'top-center'",
            "default": "'bottom-right'",
            "description": "Fixed position (when fixed=true)"
          },
          "direction": {
            "type": "'up' | 'down' | 'left' | 'right'",
            "default": "'up'",
            "description": "Direction actions expand"
          },
          "trigger": {
            "type": "'hover' | 'click'",
            "default": "'hover'",
            "description": "How to open the speed dial"
          },
          "layout": {
            "type": "'linear' | 'circle' | 'semi-circle'",
            "default": "'linear'",
            "description": "Action layout pattern"
          },
          "fixed": {
            "type": "boolean",
            "default": "false",
            "description": "Use fixed positioning"
          },
          "disabled": {
            "type": "boolean",
            "default": "false",
            "description": "Disable the speed dial"
          },
          "showLabels": {
            "type": "boolean",
            "default": "true",
            "description": "Show text labels next to action icons"
          },
          "showTooltip": {
            "type": "boolean",
            "default": "false",
            "description": "Show native tooltip on actions"
          },
          "mask": {
            "type": "boolean",
            "default": "false",
            "description": "Show background overlay when open"
          },
          "open": {
            "type": "boolean",
            "description": "Controlled open state"
          },
          "onOpenChange": {
            "type": "(open: boolean) => void",
            "description": "Callback when open state changes"
          },
          "className": {
            "type": "string",
            "description": "Additional CSS class"
          },
          "ariaLabel": {
            "type": "string",
            "description": "Accessible label"
          },
          "id": {
            "type": "string",
            "description": "HTML id attribute"
          }
        }
      }
    },
    "FieldLabel": {
      "name": "FieldLabel",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicLabel",
          "code": "import React from 'react';\nimport { FieldLabel, TextInput } from '../../../components';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst BasicLabel: React.FC = () => {\n    return (\n        <ComponentDemo title=\"Basic Label\" description=\"Simple field label\" centered={false}>\n            <FieldLabel label=\"Email Address\">\n                <TextInput id=\"basic-input\" placeholder=\"Enter your email\" />\n            </FieldLabel>\n        </ComponentDemo>\n    );\n};\n\nexport default BasicLabel;\n"
        },
        {
          "title": "CombinedStates",
          "code": "import React from 'react';\nimport { FieldLabel, TextInput } from '../../../components';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst CombinedStates: React.FC = () => {\n    return (\n        <ComponentDemo title=\"Combined States\" description=\"Multiple form fields with different label states\" centered={false}>\n            <div className=\"space-y-4 max-w-md\">\n                <FieldLabel label=\"Full Name\" required>\n                    <TextInput id=\"name\" placeholder=\"John Doe\" />\n                </FieldLabel>\n                <FieldLabel label=\"Phone Number\">\n                    <TextInput id=\"phone\" placeholder=\"+1 (555) 123-4567\" />\n                </FieldLabel>\n                <FieldLabel label=\"Email Address\" error=\"Please enter a valid email\">\n                    <TextInput id=\"email-error\" placeholder=\"invalid-email\" />\n                </FieldLabel>\n                <FieldLabel label=\"Bio\" optional>\n                    <TextInput id=\"bio\" placeholder=\"Tell us about yourself (optional)\" />\n                </FieldLabel>\n                <FieldLabel label=\"Account ID\" disabled>\n                    <TextInput id=\"frozen-field\" placeholder=\"ACC-00123\" disabled />\n                </FieldLabel>\n            </div>\n        </ComponentDemo>\n    );\n};\n\nexport default CombinedStates;\n"
        },
        {
          "title": "DisabledState",
          "code": "import React from 'react';\nimport { FieldLabel, TextInput } from '../../../components';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst DisabledState: React.FC = () => {\n    return (\n        <ComponentDemo title=\"Disabled State\" description=\"Label in disabled state\" centered={false}>\n            <FieldLabel label=\"Disabled Field\" disabled>\n                <TextInput id=\"disabled-input\" placeholder=\"Disabled input\" disabled />\n            </FieldLabel>\n        </ComponentDemo>\n    );\n};\n\nexport default DisabledState;\n"
        },
        {
          "title": "ErrorState",
          "code": "import React from 'react';\nimport { FieldLabel, TextInput } from '../../../components';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst ErrorState: React.FC = () => {\n    return (\n        <ComponentDemo title=\"Error State\" description=\"Label in error state\" centered={false}>\n            <FieldLabel label=\"Password\" error=\"This field has an error\">\n                <TextInput id=\"error-input\" placeholder=\"Invalid input\" />\n            </FieldLabel>\n        </ComponentDemo>\n    );\n};\n\nexport default ErrorState;\n"
        },
        {
          "title": "OptionalField",
          "code": "import React from 'react';\nimport { FieldLabel, TextInput } from '../../../components';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst OptionalField: React.FC = () => {\n    return (\n        <ComponentDemo title=\"Optional Field\" description=\"Label with optional indicator\" centered={false}>\n            <FieldLabel label=\"Middle Name\" optional>\n                <TextInput id=\"optional-input\" placeholder=\"Optional field\" />\n            </FieldLabel>\n        </ComponentDemo>\n    );\n};\n\nexport default OptionalField;\n"
        },
        {
          "title": "RequiredField",
          "code": "import React from 'react';\nimport { FieldLabel, TextInput } from '../../../components';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst RequiredField: React.FC = () => {\n    return (\n        <ComponentDemo title=\"Required Field\" description=\"Label with required indicator\" centered={false}>\n            <FieldLabel label=\"Username\" required>\n                <TextInput id=\"required-input\" placeholder=\"Required field\" />\n            </FieldLabel>\n        </ComponentDemo>\n    );\n};\n\nexport default RequiredField;\n"
        }
      ],
      "props": {
        "fieldLabelProps": {
          "htmlFor": {
            "type": "string",
            "description": "Associates the label with a form control"
          },
          "children": {
            "type": "ReactNode",
            "required": true,
            "description": "Label content"
          },
          "required": {
            "type": "boolean",
            "default": false,
            "description": "Shows required indicator"
          },
          "optional": {
            "type": "boolean",
            "default": false,
            "description": "Shows optional indicator"
          },
          "disabled": {
            "type": "boolean",
            "default": false,
            "description": "Disabled state styling"
          },
          "error": {
            "type": "boolean",
            "default": false,
            "description": "Error state styling"
          },
          "className": {
            "type": "string",
            "description": "Additional CSS classes"
          }
        }
      },
      "storyDir": "field-label"
    },
    "InfiniteScroll": {
      "name": "InfiniteScroll",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React, { useCallback, useState } from 'react';\nimport { InfiniteScroll } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst pageSize = 20;\nconst totalItems = 100;\n\nconst generateItems = (start: number, count: number) =>\n    Array.from({ length: count }, (_, i) => ({\n        id: start + i,\n        title: `Item ${start + i + 1}`,\n        description: `Description for item ${start + i + 1}`,\n    }));\n\nconst code = `import { InfiniteScroll } from 'fluxo-ui';\n\nconst [items, setItems] = useState(generateItems(0, 20));\nconst [hasMore, setHasMore] = useState(true);\n\nconst loadMore = async () => {\n  await new Promise((r) => setTimeout(r, 1000));\n  const newItems = generateItems(items.length, 20);\n  setItems((prev) => [...prev, ...newItems]);\n  if (items.length + 20 >= 100) setHasMore(false);\n};\n\n<InfiniteScroll loadMore={loadMore} hasMore={hasMore}>\n  {items.map((item) => (\n    <div key={item.id}>{item.title}</div>\n  ))}\n</InfiniteScroll>`;\n\nconst BasicUsage: React.FC = () => {\n    const [items, setItems] = useState(() => generateItems(0, pageSize));\n    const [hasMore, setHasMore] = useState(true);\n\n    const loadMore = useCallback(async () => {\n        await new Promise((r) => setTimeout(r, 1000));\n        setItems((prev) => {\n            const newItems = generateItems(prev.length, pageSize);\n            const all = [...prev, ...newItems];\n            if (all.length >= totalItems) {\n                setHasMore(false);\n            }\n            return all;\n        });\n    }, []);\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Scrollable List\"\n                description=\"Scroll down to automatically load more items. Shows a spinner during loading and end message when all items are loaded.\"\n                centered={false}\n            >\n                <div className=\"h-80 overflow-y-auto border border-gray-200 dark:border-gray-700 rounded-lg\" id=\"scroll-container\">\n                    <InfiniteScroll loadMore={loadMore} hasMore={hasMore} scrollableTarget=\"scroll-container\">\n                        <div className=\"divide-y divide-gray-100 dark:divide-gray-800\">\n                            {items.map((item) => (\n                                <div key={item.id} className=\"px-4 py-3\">\n                                    <div className=\"font-medium\">{item.title}</div>\n                                    <div className=\"text-sm opacity-60\">{item.description}</div>\n                                </div>\n                            ))}\n                        </div>\n                    </InfiniteScroll>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "ErrorHandling",
          "code": "import React, { useCallback, useState } from 'react';\nimport { InfiniteScroll } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst generateItems = (start: number, count: number) =>\n    Array.from({ length: count }, (_, i) => ({\n        id: start + i,\n        title: `Record ${start + i + 1}`,\n    }));\n\nconst code = `import { InfiniteScroll } from 'fluxo-ui';\n\nconst [error, setError] = useState<string | null>(null);\n\nconst loadMore = async () => {\n  await new Promise((r) => setTimeout(r, 800));\n  // Simulate random failures\n  if (Math.random() > 0.5) {\n    throw new Error('Network error');\n  }\n  setItems((prev) => [...prev, ...newItems]);\n};\n\n<InfiniteScroll\n  loadMore={loadMore}\n  hasMore={hasMore}\n  error={error}\n  onRetry={() => { setError(null); loadMore(); }}\n/>`;\n\nconst ErrorHandling: React.FC = () => {\n    const [items, setItems] = useState(() => generateItems(0, 10));\n    const [hasMore, setHasMore] = useState(true);\n    const [error, setError] = useState<string | null>(null);\n    const loadCountRef = React.useRef(0);\n\n    const loadMore = useCallback(async () => {\n        await new Promise((r) => setTimeout(r, 800));\n        loadCountRef.current++;\n        {\n            const next = loadCountRef.current;\n            if (next % 2 === 0) {\n                setError('Failed to load data. Please try again.');\n                return;\n            }\n            setItems((prevItems) => {\n                const newItems = generateItems(prevItems.length, 10);\n                const all = [...prevItems, ...newItems];\n                if (all.length >= 50) {\n                    setHasMore(false);\n                }\n                return all;\n            });\n        }\n    }, []);\n\n    const handleRetry = useCallback(() => {\n        setError(null);\n    }, []);\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Error Handling with Retry\"\n                description=\"When loading fails, an error message with a retry button is displayed. Every other load attempt simulates a failure.\"\n                centered={false}\n            >\n                <div className=\"h-72 overflow-y-auto border border-gray-200 dark:border-gray-700 rounded-lg\" id=\"error-scroll-container\">\n                    <InfiniteScroll\n                        loadMore={loadMore}\n                        hasMore={hasMore}\n                        error={error}\n                        onRetry={handleRetry}\n                        scrollableTarget=\"error-scroll-container\"\n                    >\n                        <div className=\"divide-y divide-gray-100 dark:divide-gray-800\">\n                            {items.map((item) => (\n                                <div key={item.id} className=\"px-4 py-3\">\n                                    <div className=\"font-medium\">{item.title}</div>\n                                </div>\n                            ))}\n                        </div>\n                    </InfiniteScroll>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default ErrorHandling;\n"
        }
      ],
      "props": {
        "infiniteScrollProps": {
          "loadMore": {
            "type": "() => Promise<void>",
            "required": true,
            "description": "Async function to load more data."
          },
          "hasMore": {
            "type": "boolean",
            "required": true,
            "description": "Whether there is more data to load."
          },
          "isLoading": {
            "type": "boolean",
            "default": "false",
            "description": "External loading state control."
          },
          "error": {
            "type": "string | null",
            "description": "Error message to display."
          },
          "onRetry": {
            "type": "() => void",
            "description": "Called when the retry button is clicked."
          },
          "threshold": {
            "type": "number",
            "default": "200",
            "description": "Pixel distance from bottom to trigger loading."
          },
          "loader": {
            "type": "ReactNode",
            "description": "Custom loading indicator."
          },
          "endMessage": {
            "type": "ReactNode",
            "description": "Message shown when all data is loaded."
          },
          "errorMessage": {
            "type": "ReactNode",
            "description": "Custom error display (overrides default)."
          },
          "scrollableTarget": {
            "type": "string | HTMLElement",
            "description": "ID or element of the scrollable container."
          },
          "inverse": {
            "type": "boolean",
            "default": "false",
            "description": "Load content at the top (chat-style)."
          },
          "endAnnouncement": {
            "type": "string",
            "description": "Text announced via aria-live region when the end of the feed is reached. Defaults to 'You have reached the end of the list.'"
          },
          "children": {
            "type": "ReactNode",
            "required": true,
            "description": "List content to display."
          },
          "className": {
            "type": "string",
            "description": "Additional CSS class for the container."
          }
        }
      },
      "storyDir": "infinite-scroll"
    },
    "InputGroup": {
      "name": "InputGroup",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "EmailInput",
          "code": "import React from 'react';\nimport { InputGroup, TextInput } from '../../../components';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst EmailInput: React.FC = () => {\n    return (\n        <ComponentDemo title=\"Email Input\" description=\"Input with @ symbol addon\">\n            <div className=\"w-full max-w-96\">\n                <InputGroup>\n                    <TextInput placeholder=\"username\" />\n                    <span>@</span>\n                    <TextInput placeholder=\"domain.com\" />\n                </InputGroup>\n            </div>\n        </ComponentDemo>\n    );\n};\n\nexport default EmailInput;\n"
        },
        {
          "title": "FileUpload",
          "code": "import React from 'react';\nimport { Button, InputGroup, TextInput } from '../../../components';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst FileUpload: React.FC = () => {\n    return (\n        <ComponentDemo title=\"File Upload\" description=\"File input with upload button\">\n            <div className=\"w-full max-w-96\">\n                <InputGroup>\n                    <TextInput placeholder=\"Choose file...\" readonly />\n                    <Button layout=\"outlined\">Browse</Button>\n                    <Button>Upload</Button>\n                </InputGroup>\n            </div>\n        </ComponentDemo>\n    );\n};\n\nexport default FileUpload;\n"
        },
        {
          "title": "PhoneNumber",
          "code": "import React from 'react';\nimport { InputGroup, TextInput } from '../../../components';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst PhoneNumber: React.FC = () => {\n    return (\n        <ComponentDemo title=\"Phone Number\" description=\"Input with country code prefix\">\n            <div className=\"w-full max-w-80\">\n                <InputGroup>\n                    <span>+1</span>\n                    <TextInput placeholder=\"(555) 000-0000\" />\n                </InputGroup>\n            </div>\n        </ComponentDemo>\n    );\n};\n\nexport default PhoneNumber;\n"
        },
        {
          "title": "PriceInput",
          "code": "import React from 'react';\nimport { InputGroup, TextInput } from '../../../components';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst PriceInput: React.FC = () => {\n    return (\n        <ComponentDemo title=\"Price Input\" description=\"Input with currency prefix and suffix\">\n            <div className=\"w-full max-w-80\">\n                <InputGroup>\n                    <span>$</span>\n                    <TextInput placeholder=\"0.00\" />\n                    <span>USD</span>\n                </InputGroup>\n            </div>\n        </ComponentDemo>\n    );\n};\n\nexport default PriceInput;\n"
        },
        {
          "title": "SearchInput",
          "code": "import React, { useState } from 'react';\nimport { Button, InputGroup, TextInput } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst SearchInput: React.FC = () => {\n    const [searchValue, setSearchValue] = useState('');\n\n    return (\n        <>\n            <ComponentDemo title=\"Search Input with Button\" description=\"Text input grouped with a search button\">\n                <div className=\"w-full max-w-96\">\n                    <InputGroup>\n                        <TextInput value={searchValue} placeholder=\"Search...\" onChange={(e) => setSearchValue(e.value)} />\n                        <Button>Search</Button>\n                    </InputGroup>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock\n                    title=\"Basic Example\"\n                    code={`<InputGroup>\n  <TextInput value={value} placeholder=\"Search...\" onChange={(e) => setValue(e.value)} />\n  <Button>Search</Button>\n</InputGroup>`}\n                />\n            </div>\n        </>\n    );\n};\n\nexport default SearchInput;\n"
        },
        {
          "title": "UrlInput",
          "code": "import React, { useState } from 'react';\nimport { Button, InputGroup, TextInput } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst UrlInput: React.FC = () => {\n    const [urlValue, setUrlValue] = useState('');\n\n    return (\n        <>\n            <ComponentDemo title=\"URL Input with Protocol\" description=\"Input with text prefix and multiple buttons\">\n                <div className=\"w-full max-w-lg\">\n                    <InputGroup>\n                        <span>https://</span>\n                        <TextInput\n                            value={urlValue}\n                            placeholder=\"example.com\"\n                            onChange={(e) => setUrlValue(e.value)}\n                        />\n                        <Button layout=\"outlined\">Copy</Button>\n                        <Button>Visit</Button>\n                    </InputGroup>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock\n                    code={`<InputGroup>\n  <span>https://</span>\n  <TextInput value={url} placeholder=\"example.com\" onChange={(e) => setUrl(e.value)} />\n  <Button layout=\"outlined\">Copy</Button>\n  <Button>Visit</Button>\n</InputGroup>`}\n                />\n            </div>\n        </>\n    );\n};\n\nexport default UrlInput;\n"
        }
      ],
      "props": {
        "inputGroupProps": {
          "children": {
            "type": "ReactNode",
            "required": true,
            "description": "Inputs and addons. `<span>`, `<div>`, `<label>`, `<small>`, `<p>` and any element with `data-input-group-addon` are treated as addons; everything else (TextInput, NumericInput, Button, etc.) renders inline. Fragments are flattened automatically."
          },
          "ariaLabel": {
            "type": "string",
            "description": "Accessible label for the group (sets aria-label on role=group)"
          },
          "ariaLabelledBy": {
            "type": "string",
            "description": "ID of the element that labels the group"
          },
          "disabled": {
            "type": "boolean",
            "default": false,
            "description": "Disable the entire group (sets aria-disabled)"
          },
          "className": {
            "type": "string",
            "description": "Additional CSS classes"
          }
        }
      },
      "storyDir": "input-group"
    },
    "InputSwitch": {
      "name": "InputSwitch",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import cn from 'classnames';\nimport React, { useState } from 'react';\nimport { InputSwitch } from '../../../components';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\n\nconst BasicUsage: React.FC = () => {\n    const { isDark } = useStoryTheme();\n    const [basicSwitch, setBasicSwitch] = useState(false);\n\n    return (\n        <ComponentDemo title=\"Basic Switch\" description=\"Simple on/off toggle switch\">\n            <div className=\"flex items-center space-x-4\">\n                <InputSwitch checked={basicSwitch} onChange={(e) => setBasicSwitch(e.value)} />\n                <span className={cn({ 'text-gray-300': isDark, 'text-gray-700': !isDark })}>{basicSwitch ? 'Enabled' : 'Disabled'}</span>\n            </div>\n        </ComponentDemo>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "CustomLabels",
          "code": "import React from 'react';\nimport { InputSwitch } from '../../../components';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst CustomLabels: React.FC = () => {\n    return (\n        <ComponentDemo title=\"Custom Labels\" description=\"Switches with custom on/off labels\">\n            <div className=\"flex flex-col space-y-4\">\n                <div className=\"flex items-center space-x-4\">\n                    <InputSwitch\n                        checked={true}\n                        onChange={(e) => console.log('Yes/No:', e.value)}\n                        onLabel=\"Yes\"\n                        offLabel=\"No\"\n                    />\n                </div>\n                <div className=\"flex items-center space-x-4\">\n                    <InputSwitch\n                        checked={false}\n                        onChange={(e) => console.log('Active/Inactive:', e.value)}\n                        onLabel=\"Active\"\n                        offLabel=\"Inactive\"\n                    />\n                </div>\n                <div className=\"flex items-center space-x-4\">\n                    <InputSwitch\n                        checked={true}\n                        onChange={(e) => console.log('Enabled/Disabled:', e.value)}\n                        onLabel=\"Enabled\"\n                        offLabel=\"Disabled\"\n                    />\n                </div>\n            </div>\n        </ComponentDemo>\n    );\n};\n\nexport default CustomLabels;\n"
        },
        {
          "title": "DisabledStates",
          "code": "import cn from 'classnames';\nimport React from 'react';\nimport { InputSwitch } from '../../../components';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\n\nconst DisabledStates: React.FC = () => {\n    const { isDark } = useStoryTheme();\n\n    return (\n        <ComponentDemo title=\"Disabled States\" description=\"Switches in disabled state\">\n            <div className=\"flex items-center space-x-8\">\n                <div className=\"text-center\">\n                    <InputSwitch checked={false} disabled />\n                    <p className={cn('text-sm mt-2', { 'text-gray-400': isDark, 'text-gray-600': !isDark })}>Disabled Off</p>\n                </div>\n                <div className=\"text-center\">\n                    <InputSwitch checked={true} disabled />\n                    <p className={cn('text-sm mt-2', { 'text-gray-400': isDark, 'text-gray-600': !isDark })}>Disabled On</p>\n                </div>\n            </div>\n        </ComponentDemo>\n    );\n};\n\nexport default DisabledStates;\n"
        },
        {
          "title": "FormIntegration",
          "code": "import cn from 'classnames';\nimport React from 'react';\nimport { InputSwitch } from '../../../components';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\n\nconst FormIntegration: React.FC = () => {\n    const { isDark } = useStoryTheme();\n\n    return (\n        <ComponentDemo title=\"Form Integration\" description=\"Switch integrated with form labels\">\n            <div className=\"space-y-6 max-w-md\">\n                <div className=\"flex items-center space-x-3\">\n                    <InputSwitch checked={false} onChange={(e) => console.log('Email notifications:', e.value)} />\n                    <label className={cn('cursor-pointer', { 'text-gray-300': isDark, 'text-gray-700': !isDark })}>Send me email notifications</label>\n                </div>\n\n                <div className=\"flex items-center space-x-3\">\n                    <InputSwitch checked={true} onChange={(e) => console.log('Marketing emails:', e.value)} />\n                    <label className={cn('cursor-pointer', { 'text-gray-300': isDark, 'text-gray-700': !isDark })}>I agree to receive marketing emails</label>\n                </div>\n\n                <div className=\"flex items-center space-x-3\">\n                    <InputSwitch checked={false} onChange={(e) => console.log('Terms accepted:', e.value)} />\n                    <label className={cn('cursor-pointer', { 'text-gray-300': isDark, 'text-gray-700': !isDark })}>I accept the terms and conditions</label>\n                </div>\n            </div>\n        </ComponentDemo>\n    );\n};\n\nexport default FormIntegration;\n"
        },
        {
          "title": "SettingsPanel",
          "code": "import cn from 'classnames';\nimport React, { useState } from 'react';\nimport { InputSwitch } from '../../../components';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\n\nconst SettingsPanel: React.FC = () => {\n    const { isDark } = useStoryTheme();\n    const [premiumSwitch, setPremiumSwitch] = useState(true);\n    const [notificationSwitch, setNotificationSwitch] = useState(false);\n\n    return (\n        <ComponentDemo title=\"Settings Panel\" description=\"Multiple switches in a settings-like layout\">\n            <div className=\"space-y-4 w-full max-w-80\">\n                <div className={cn('flex items-center justify-between p-4 rounded-lg border', { 'bg-gray-800 border-gray-700': isDark, 'bg-gray-100 border-gray-200': !isDark })}>\n                    <div>\n                        <h4 className={cn('font-medium', { 'text-gray-100': isDark, 'text-gray-900': !isDark })}>Premium Features</h4>\n                        <p className={cn('text-sm', { 'text-gray-400': isDark, 'text-gray-600': !isDark })}>Enable advanced functionality</p>\n                    </div>\n                    <InputSwitch checked={premiumSwitch} onChange={(e) => setPremiumSwitch(e.value)} />\n                </div>\n\n                <div className={cn('flex items-center justify-between p-4 rounded-lg border', { 'bg-gray-800 border-gray-700': isDark, 'bg-gray-100 border-gray-200': !isDark })}>\n                    <div>\n                        <h4 className={cn('font-medium', { 'text-gray-100': isDark, 'text-gray-900': !isDark })}>Notifications</h4>\n                        <p className={cn('text-sm', { 'text-gray-400': isDark, 'text-gray-600': !isDark })}>Receive email updates</p>\n                    </div>\n                    <InputSwitch checked={notificationSwitch} onChange={(e) => setNotificationSwitch(e.value)} />\n                </div>\n            </div>\n        </ComponentDemo>\n    );\n};\n\nexport default SettingsPanel;\n"
        }
      ],
      "props": {
        "inputSwitchProps": {
          "checked": {
            "type": "boolean",
            "default": "false",
            "description": "Whether the switch is in the on position"
          },
          "onChange": {
            "type": "(event: ComponentEvent<boolean>) => void",
            "description": "Callback fired when switch state changes. Receives event object with value, name, and args properties"
          },
          "onLabel": {
            "type": "string",
            "default": "'On'",
            "description": "Label text displayed when switch is on"
          },
          "offLabel": {
            "type": "string",
            "default": "'Off'",
            "description": "Label text displayed when switch is off"
          },
          "label": {
            "type": "string",
            "description": "Optional descriptive label for the toggle's purpose, rendered before the switch and used for screen readers"
          },
          "ariaLabel": {
            "type": "string",
            "description": "Accessible label override for the switch button"
          },
          "size": {
            "type": "'xs' | 'sm' | 'md' | 'lg' | 'xl'",
            "default": "'md'",
            "description": "Switch size"
          },
          "disabled": {
            "type": "boolean",
            "default": "false",
            "description": "Whether the switch is disabled"
          },
          "required": {
            "type": "boolean",
            "default": "false",
            "description": "Mark the switch as required"
          },
          "id": {
            "type": "string",
            "description": "HTML id attribute for the switch input"
          },
          "name": {
            "type": "string",
            "description": "Name attribute for the switch input (used in forms)"
          },
          "args": {
            "type": "any",
            "description": "Additional arguments passed to onChange handler"
          },
          "className": {
            "type": "string",
            "description": "Additional CSS classes for the container"
          }
        }
      },
      "storyDir": "input-switch"
    },
    "ListBox": {
      "name": "ListBox",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "DisabledState",
          "code": "import React from 'react';\nimport { ListBox } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { frameworkOptions } from './list-box-story-data';\n\nconst DisabledState: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo title=\"Fully disabled\" description=\"The entire list is non-interactive when disabled is true.\">\n                <div className=\"w-full max-w-72\">\n                    <ListBox options={frameworkOptions} value=\"react\" disabled />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={`<ListBox options={options} value={value} disabled />`} />\n            </div>\n        </>\n    );\n};\n\nexport default DisabledState;\n"
        },
        {
          "title": "GroupedList",
          "code": "import cn from 'classnames';\nimport React, { useState } from 'react';\nimport { ListBox } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\nimport { groupedOptions } from './list-box-story-data';\n\nconst GroupedList: React.FC = () => {\n    const { isDark } = useStoryTheme();\n    const [grouped, setGrouped] = useState<string[]>([]);\n\n    return (\n        <>\n            <ComponentDemo title=\"Group by category\" description=\"Items grouped by their category with sticky group headers.\">\n                <div className=\"w-full max-w-72\">\n                    <ListBox\n                        options={groupedOptions}\n                        value={grouped}\n                        onChange={(v) => setGrouped(v as string[])}\n                        multiple\n                        grouped\n                        groupBy={(opt) => opt.metadata?.category ?? 'Other'}\n                        maxHeight={280}\n                    />\n                </div>\n                {grouped.length > 0 && (\n                    <p className={cn('text-sm mt-3', { 'text-gray-400': isDark, 'text-gray-600': !isDark })}>\n                        Selected: <span className={cn('font-medium', { 'text-gray-100': isDark, 'text-gray-900': !isDark })}>{grouped.join(', ')}</span>\n                    </p>\n                )}\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock\n                    code={`<ListBox\n  options={options}\n  value={values}\n  onChange={(v) => setValues(v as string[])}\n  multiple\n  grouped\n  groupBy={(opt) => opt.metadata?.category ?? 'Other'}\n  maxHeight={280}\n/>`}\n                />\n            </div>\n        </>\n    );\n};\n\nexport default GroupedList;\n"
        },
        {
          "title": "MultipleSelection",
          "code": "import cn from 'classnames';\nimport React, { useState } from 'react';\nimport { ListBox } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\nimport { roleOptions } from './list-box-story-data';\n\nconst MultipleSelection: React.FC = () => {\n    const { isDark } = useStoryTheme();\n    const [multi, setMulti] = useState<string[]>([]);\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Multi-select with select-all\"\n                description=\"Select multiple items. Shift-click or use the Select All checkbox.\"\n            >\n                <div className=\"w-full max-w-72\">\n                    <ListBox\n                        options={roleOptions}\n                        value={multi}\n                        onChange={(v) => setMulti(v as string[])}\n                        multiple\n                        selectAll\n                        clearable\n                    />\n                </div>\n                {multi.length > 0 && (\n                    <p className={cn('text-sm mt-3', { 'text-gray-400': isDark, 'text-gray-600': !isDark })}>\n                        Selected: <span className={cn('font-medium', { 'text-gray-100': isDark, 'text-gray-900': !isDark })}>{multi.join(', ')}</span>\n                    </p>\n                )}\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock\n                    code={`const [values, setValues] = useState<string[]>([]);\n\n<ListBox\n  options={options}\n  value={values}\n  onChange={(v) => setValues(v as string[])}\n  multiple\n  selectAll\n  clearable\n/>`}\n                />\n            </div>\n        </>\n    );\n};\n\nexport default MultipleSelection;\n"
        },
        {
          "title": "SearchableList",
          "code": "import React, { useState } from 'react';\nimport { ListBox } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { frameworkOptions } from './list-box-story-data';\n\nconst SearchableList: React.FC = () => {\n    const [searchable, setSearchable] = useState<string>();\n\n    return (\n        <>\n            <ComponentDemo title=\"With search filter\" description=\"Type to filter the list in real time.\">\n                <div className=\"w-full max-w-72\">\n                    <ListBox\n                        options={frameworkOptions}\n                        value={searchable}\n                        onChange={(v) => setSearchable(v as string)}\n                        searchable\n                        searchPlaceholder=\"Search frameworks...\"\n                    />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock\n                    code={`<ListBox\n  options={options}\n  value={value}\n  onChange={setValue}\n  searchable\n  searchPlaceholder=\"Search frameworks...\"\n/>`}\n                />\n            </div>\n        </>\n    );\n};\n\nexport default SearchableList;\n"
        },
        {
          "title": "SingleSelection",
          "code": "import cn from 'classnames';\nimport React, { useState } from 'react';\nimport { ListBox } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\nimport { frameworkOptions } from './list-box-story-data';\n\nconst SingleSelection: React.FC = () => {\n    const { isDark } = useStoryTheme();\n    const [single, setSingle] = useState<string>();\n\n    return (\n        <>\n            <ComponentDemo title=\"Basic single select\" description=\"Click an item to select it.\">\n                <div className=\"flex flex-col items-center gap-3\">\n                    <div className=\"w-full max-w-72\">\n                        <ListBox options={frameworkOptions} value={single} onChange={(v) => setSingle(v as string)} />\n                    </div>\n                    {single && (\n                        <p className={cn('text-sm', { 'text-gray-400': isDark, 'text-gray-600': !isDark })}>\n                            Selected: <span className={cn('font-medium', { 'text-gray-100': isDark, 'text-gray-900': !isDark })}>{single}</span>\n                        </p>\n                    )}\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock\n                    code={`const [value, setValue] = useState<string>();\n\n<ListBox\n  options={frameworkOptions}\n  value={value}\n  onChange={(v) => setValue(v as string)}\n/>`}\n                />\n            </div>\n        </>\n    );\n};\n\nexport default SingleSelection;\n"
        }
      ],
      "props": {
        "listBoxProps": {
          "options": {
            "type": "ListBoxOption[]",
            "required": true,
            "description": "Array of options to display."
          },
          "value": {
            "type": "T | T[]",
            "description": "Currently selected value or array of values (for multiple selection)."
          },
          "onChange": {
            "type": "(value: T | T[]) => void",
            "description": "Called when selection changes."
          },
          "multiple": {
            "type": "boolean",
            "default": "false",
            "description": "Allow selecting multiple items."
          },
          "searchable": {
            "type": "boolean",
            "default": "false",
            "description": "Show a search input above the list."
          },
          "searchPlaceholder": {
            "type": "string",
            "description": "Placeholder text for the search input."
          },
          "grouped": {
            "type": "boolean",
            "default": "false",
            "description": "Group items using the groupBy function."
          },
          "groupBy": {
            "type": "(option: ListBoxOption) => string",
            "description": "Returns the group name for each option."
          },
          "selectAll": {
            "type": "boolean",
            "default": "false",
            "description": "Show a Select All checkbox (requires multiple)."
          },
          "clearable": {
            "type": "boolean",
            "default": "false",
            "description": "Show a Clear All button."
          },
          "disabled": {
            "type": "boolean",
            "default": "false",
            "description": "Disable all interactions."
          },
          "emptyMessage": {
            "type": "string",
            "description": "Message shown when the option list is empty."
          },
          "maxHeight": {
            "type": "string | number",
            "description": "Max height of the scrollable list."
          },
          "itemTemplate": {
            "type": "(option: ListBoxOption) => ReactNode",
            "description": "Custom renderer for each option item."
          },
          "compareFn": {
            "type": "(a: T, b: T) => boolean",
            "description": "Custom equality comparator for option values. Defaults to deep-equal (JSON-stringify based) for objects."
          },
          "ariaLabel": {
            "type": "string",
            "description": "Accessible label for the listbox."
          },
          "ariaLabelledBy": {
            "type": "string",
            "description": "ID of the element that labels the listbox."
          }
        }
      },
      "storyDir": "list-box"
    },
    "MaskedInput": {
      "name": "MaskedInput",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "CustomSlotChar",
          "code": "import cn from 'classnames';\nimport React from 'react';\nimport { MaskedInput } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\n\nconst code = `<MaskedInput mask=\"(999) 999-9999\" slotChar=\"#\" value={v} onChange={(e) => setV(e.value)} />\n<MaskedInput mask=\"99/99/9999\"     slotChar=\"·\" value={v} onChange={(e) => setV(e.value)} />`;\n\nconst CustomSlotChar: React.FC = () => {\n    const { isDark } = useStoryTheme();\n\n    const labelClass = cn('block text-xs font-medium mb-1', {\n        'text-gray-400': isDark,\n        'text-gray-600': !isDark,\n    });\n\n    return (\n        <>\n            <ComponentDemo title=\"Custom slotChar\">\n                <div className=\"w-full max-w-sm space-y-4\">\n                    <div className=\"space-y-1\">\n                        <label className={labelClass}>slotChar=\"#\"</label>\n                        <MaskedInput mask=\"(999) 999-9999\" value=\"\" onChange={() => {}} slotChar=\"#\" />\n                    </div>\n                    <div className=\"space-y-1\">\n                        <label className={labelClass}>slotChar=\"·\"</label>\n                        <MaskedInput mask=\"99/99/9999\" value=\"\" onChange={() => {}} slotChar=\"·\" />\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default CustomSlotChar;\n"
        },
        {
          "title": "IncludeLiterals",
          "code": "import cn from 'classnames';\nimport React from 'react';\nimport { MaskedInput } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\n\nconst code = `<MaskedInput\n  mask=\"(999) 999-9999\"\n  includeLiterals={false}\n  value={phone}\n  onChange={(e) => setPhone(e.value)}\n  onRawChange={(raw, masked) => console.log(raw, masked)}\n/>`;\n\nconst IncludeLiterals: React.FC = () => {\n    const { isDark } = useStoryTheme();\n\n    const labelClass = cn('block text-xs font-medium mb-1', {\n        'text-gray-400': isDark,\n        'text-gray-600': !isDark,\n    });\n\n    return (\n        <>\n            <ComponentDemo title=\"includeLiterals comparison\">\n                <div className=\"w-full max-w-xl grid grid-cols-1 sm:grid-cols-2 gap-6\">\n                    <div className=\"space-y-2\">\n                        <label className={labelClass}>\n                            includeLiterals=<strong>true</strong> (default)\n                        </label>\n                        <MaskedInput mask=\"(999) 999-9999\" value=\"\" onChange={() => {}} includeLiterals={true} />\n                        <p className={cn('text-xs', { 'text-gray-500': isDark, 'text-gray-400': !isDark })}>\n                            onChange emits e.g. <code className=\"font-mono\">(123) 456-7890</code>\n                        </p>\n                    </div>\n                    <div className=\"space-y-2\">\n                        <label className={labelClass}>\n                            includeLiterals=<strong>false</strong>\n                        </label>\n                        <MaskedInput mask=\"(999) 999-9999\" value=\"\" onChange={() => {}} includeLiterals={false} />\n                        <p className={cn('text-xs', { 'text-gray-500': isDark, 'text-gray-400': !isDark })}>\n                            onChange emits e.g. <code className=\"font-mono\">1234567890</code>\n                        </p>\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default IncludeLiterals;\n"
        },
        {
          "title": "InputStates",
          "code": "import cn from 'classnames';\nimport React from 'react';\nimport { MaskedInput } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\n\nconst code = `<MaskedInput mask=\"(999) 999-9999\" value={v} onChange={(e) => setV(e.value)} />\n<MaskedInput mask=\"(999) 999-9999\" value={v} onChange={(e) => setV(e.value)} disabled />\n<MaskedInput mask=\"(999) 999-9999\" value={v} onChange={(e) => setV(e.value)} readonly />\n<MaskedInput mask=\"(999) 999-9999\" value={v} onChange={(e) => setV(e.value)} required />`;\n\nconst InputStates: React.FC = () => {\n    const { isDark } = useStoryTheme();\n\n    const labelClass = cn('block text-xs font-medium mb-1', {\n        'text-gray-400': isDark,\n        'text-gray-600': !isDark,\n    });\n\n    return (\n        <>\n            <ComponentDemo title=\"Disabled and Read-only\">\n                <div className=\"w-full max-w-sm space-y-4\">\n                    <div className=\"space-y-1\">\n                        <label className={labelClass}>Normal</label>\n                        <MaskedInput mask=\"(999) 999-9999\" value=\"\" onChange={() => {}} />\n                    </div>\n                    <div className=\"space-y-1\">\n                        <label className={labelClass}>Disabled</label>\n                        <MaskedInput mask=\"(999) 999-9999\" value=\"5550001111\" onChange={() => {}} disabled />\n                    </div>\n                    <div className=\"space-y-1\">\n                        <label className={labelClass}>Read-only</label>\n                        <MaskedInput mask=\"(999) 999-9999\" value=\"5550001111\" onChange={() => {}} readonly />\n                    </div>\n                    <div className=\"space-y-1\">\n                        <label className={labelClass}>Required (empty)</label>\n                        <MaskedInput mask=\"(999) 999-9999\" value=\"\" onChange={() => {}} required />\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default InputStates;\n"
        },
        {
          "title": "KeyboardNavigation",
          "code": "import cn from 'classnames';\nimport React from 'react';\nimport { useStoryTheme } from '../../StoryThemeContext';\n\nconst keyboardRows = [\n    { key: 'Any valid char', behaviour: 'Insert into the current editable slot and advance cursor' },\n    { key: 'Backspace', behaviour: 'Clear the slot to the left of the cursor' },\n    { key: 'Delete', behaviour: 'Clear the slot under the cursor' },\n    { key: '← / →', behaviour: 'Jump to previous / next editable slot' },\n    { key: 'Home', behaviour: 'Jump to the first editable slot' },\n    { key: 'End', behaviour: 'Jump to the slot after the last filled character' },\n    { key: 'Tab', behaviour: 'Default browser tab-focus behaviour (not intercepted)' },\n    { key: 'Paste', behaviour: 'Insert pasted text character-by-character, skipping non-matching chars' },\n];\n\nconst KeyboardNavigation: React.FC = () => {\n    const { isDark } = useStoryTheme();\n\n    return (\n        <div\n            className={cn('rounded-lg border overflow-hidden text-sm', {\n                'border-white/10 bg-white/4': isDark,\n                'border-gray-200 bg-white': !isDark,\n            })}\n        >\n            <table className=\"w-full\">\n                <thead>\n                    <tr className={cn('text-xs font-semibold uppercase tracking-wider', {\n                        'bg-white/6 text-gray-500': isDark,\n                        'bg-gray-50 text-gray-500': !isDark,\n                    })}>\n                        <th className=\"px-4 py-2 text-left\">Key</th>\n                        <th className=\"px-4 py-2 text-left\">Behaviour</th>\n                    </tr>\n                </thead>\n                <tbody className={cn('divide-y', { 'divide-white/6': isDark, 'divide-gray-100': !isDark })}>\n                    {keyboardRows.map((row) => (\n                        <tr key={row.key} className={cn({ 'text-gray-300': isDark, 'text-gray-700': !isDark })}>\n                            <td className=\"px-4 py-2 font-mono font-medium\">{row.key}</td>\n                            <td className=\"px-4 py-2\">{row.behaviour}</td>\n                        </tr>\n                    ))}\n                </tbody>\n            </table>\n        </div>\n    );\n};\n\nexport default KeyboardNavigation;\n"
        },
        {
          "title": "MaskExamples",
          "code": "import cn from 'classnames';\nimport React, { useState } from 'react';\nimport { MaskedInput } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\n\nconst phoneCode = `import { MaskedInput } from 'fluxo-ui';\n\nconst [phone, setPhone] = useState('');\n\n<MaskedInput\n  mask=\"(999) 999-9999\"\n  value={phone}\n  onChange={(e) => setPhone(e.value)}\n/>`;\n\nconst dateCode = `<MaskedInput\n  mask=\"99/99/9999\"\n  value={date}\n  onChange={(e) => setDate(e.value)}\n/>`;\n\nconst timeCode = `<MaskedInput\n  mask=\"99:99\"\n  value={time}\n  onChange={(e) => setTime(e.value)}\n/>`;\n\nconst ssnCode = `<MaskedInput\n  mask=\"999-99-9999\"\n  value={ssn}\n  onChange={(e) => setSsn(e.value)}\n/>`;\n\nconst ccCode = `<MaskedInput\n  mask=\"9999 9999 9999 9999\"\n  value={cc}\n  onChange={(e) => setCc(e.value)}\n/>`;\n\nconst ipCode = `<MaskedInput\n  mask=\"999.999.999.999\"\n  value={ip}\n  onChange={(e) => setIp(e.value)}\n/>`;\n\nconst plateCode = `<MaskedInput\n  mask=\"aaa-9999\"\n  value={plate}\n  onChange={(e) => setPlate(e.value)}\n/>`;\n\ninterface MaskDemoProps {\n    id: string;\n    title: string;\n    mask: string;\n    label: string;\n    code: string;\n    maxWidth?: string;\n    description?: string;\n}\n\nconst MaskDemo: React.FC<MaskDemoProps> = ({ title, mask, label, code: codeStr, maxWidth = 'max-w-xs', description }) => {\n    const { isDark } = useStoryTheme();\n    const [value, setValue] = useState('');\n    const [raw, setRaw] = useState('');\n\n    const labelClass = cn('block text-xs font-medium mb-1', {\n        'text-gray-400': isDark,\n        'text-gray-600': !isDark,\n    });\n\n    const valueDisplay = cn('mt-2 text-xs font-mono px-2 py-1 rounded', {\n        'bg-white/6 text-gray-400': isDark,\n        'bg-gray-100 text-gray-500': !isDark,\n    });\n\n    return (\n        <>\n            {description && (\n                <p className={cn('text-sm mb-4', { 'text-gray-400': isDark, 'text-gray-500': !isDark })}>\n                    Mask <code className=\"font-mono\">{mask}</code> — {description}\n                </p>\n            )}\n            <ComponentDemo title={title}>\n                <div className={`w-full ${maxWidth} space-y-2`}>\n                    <label className={labelClass}>{label}</label>\n                    <MaskedInput mask={mask} value={value} onChange={(e) => setValue(e.value)} onRawChange={(r) => setRaw(r)} />\n                    <div className={valueDisplay}>\n                        value: &quot;{value}&quot; &nbsp;|&nbsp; raw: &quot;{raw}&quot;\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={codeStr} />\n            </div>\n        </>\n    );\n};\n\nexport const PhoneNumber: React.FC = () => (\n    <MaskDemo\n        id=\"phone\"\n        title=\"US Phone Number\"\n        mask=\"(999) 999-9999\"\n        label=\"Phone Number\"\n        code={phoneCode}\n        description=\"digits only with formatted separators.\"\n    />\n);\n\nexport const DateInput: React.FC = () => (\n    <MaskDemo\n        id=\"date\"\n        title=\"Date (MM/DD/YYYY)\"\n        mask=\"99/99/9999\"\n        label=\"Date of Birth\"\n        code={dateCode}\n        description=\"calendar date with slash separators.\"\n    />\n);\n\nexport const TimeInput: React.FC = () => (\n    <MaskDemo\n        id=\"time\"\n        title=\"Time (HH:MM)\"\n        mask=\"99:99\"\n        label=\"Meeting Time\"\n        code={timeCode}\n        description=\"24-hour or 12-hour time input.\"\n    />\n);\n\nexport const SsnInput: React.FC = () => (\n    <MaskDemo\n        id=\"ssn\"\n        title=\"SSN\"\n        mask=\"999-99-9999\"\n        label=\"Social Security Number\"\n        code={ssnCode}\n        description=\"SSN with dash separators.\"\n    />\n);\n\nexport const CreditCard: React.FC = () => (\n    <MaskDemo\n        id=\"credit-card\"\n        title=\"Credit Card Number\"\n        mask=\"9999 9999 9999 9999\"\n        label=\"Card Number\"\n        code={ccCode}\n        maxWidth=\"max-w-sm\"\n        description=\"four groups of four digits separated by spaces.\"\n    />\n);\n\nexport const Ipv4Address: React.FC = () => (\n    <MaskDemo\n        id=\"ipv4\"\n        title=\"IPv4 Address\"\n        mask=\"999.999.999.999\"\n        label=\"IP Address\"\n        code={ipCode}\n        description=\"four octet groups with dot separators.\"\n    />\n);\n\nexport const LicensePlate: React.FC = () => (\n    <MaskDemo\n        id=\"license-plate\"\n        title=\"Vehicle License Plate\"\n        mask=\"aaa-9999\"\n        label=\"License Plate\"\n        code={plateCode}\n        description=\"three letters, a dash, then four digits.\"\n    />\n);\n"
        },
        {
          "title": "MaskSyntax",
          "code": "import cn from 'classnames';\nimport React from 'react';\nimport { useStoryTheme } from '../../StoryThemeContext';\n\nconst MaskSyntax: React.FC = () => {\n    const { isDark } = useStoryTheme();\n\n    return (\n        <div\n            className={cn('rounded-lg border overflow-hidden text-sm', {\n                'border-white/10 bg-white/4': isDark,\n                'border-gray-200 bg-white': !isDark,\n            })}\n        >\n            <table className=\"w-full\">\n                <thead>\n                    <tr className={cn('text-xs font-semibold uppercase tracking-wider', {\n                        'bg-white/6 text-gray-500': isDark,\n                        'bg-gray-50 text-gray-500': !isDark,\n                    })}>\n                        <th className=\"px-4 py-2 text-left\">Character</th>\n                        <th className=\"px-4 py-2 text-left\">Accepts</th>\n                        <th className=\"px-4 py-2 text-left\">Example slot</th>\n                    </tr>\n                </thead>\n                <tbody className={cn('divide-y', { 'divide-white/6': isDark, 'divide-gray-100': !isDark })}>\n                    {[\n                        { ch: '9', accepts: 'Digit (0–9)', ex: '5' },\n                        { ch: 'a', accepts: 'Letter (a–z, A–Z)', ex: 'B' },\n                        { ch: '*', accepts: 'Alphanumeric (a–z, A–Z, 0–9)', ex: 'X3' },\n                        { ch: 'other', accepts: 'Fixed literal separator', ex: '-, /, (, ) …' },\n                    ].map((row) => (\n                        <tr key={row.ch} className={cn({ 'text-gray-300': isDark, 'text-gray-700': !isDark })}>\n                            <td className=\"px-4 py-2 font-mono font-bold\">{row.ch}</td>\n                            <td className=\"px-4 py-2\">{row.accepts}</td>\n                            <td className={cn('px-4 py-2 font-mono', { 'text-gray-500': isDark, 'text-gray-400': !isDark })}>{row.ex}</td>\n                        </tr>\n                    ))}\n                </tbody>\n            </table>\n        </div>\n    );\n};\n\nexport default MaskSyntax;\n"
        },
        {
          "title": "PrefilledValue",
          "code": "import cn from 'classnames';\nimport React from 'react';\nimport { MaskedInput } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\n\nconst code = `<MaskedInput mask=\"(999) 999-9999\" value=\"5551234567\" onChange={(e) => setPhone(e.value)} />\n<MaskedInput mask=\"99/99/9999\"     value=\"01/15/1990\"     onChange={(e) => setDate(e.value)} />\n<MaskedInput mask=\"9999 9999 9999 9999\" value=\"4111111111111111\" onChange={(e) => setCc(e.value)} />`;\n\nconst PrefilledValue: React.FC = () => {\n    const { isDark } = useStoryTheme();\n\n    const labelClass = cn('block text-xs font-medium mb-1', {\n        'text-gray-400': isDark,\n        'text-gray-600': !isDark,\n    });\n\n    return (\n        <>\n            <ComponentDemo title=\"Pre-filled inputs\">\n                <div className=\"w-full max-w-sm space-y-4\">\n                    <div className=\"space-y-1\">\n                        <label className={labelClass}>Phone (pre-filled raw \"5551234567\")</label>\n                        <MaskedInput mask=\"(999) 999-9999\" value=\"5551234567\" onChange={() => {}} />\n                    </div>\n                    <div className=\"space-y-1\">\n                        <label className={labelClass}>Date (pre-filled \"01/15/1990\")</label>\n                        <MaskedInput mask=\"99/99/9999\" value=\"01/15/1990\" onChange={() => {}} />\n                    </div>\n                    <div className=\"space-y-1\">\n                        <label className={labelClass}>Credit Card (pre-filled \"4111111111111111\")</label>\n                        <MaskedInput mask=\"9999 9999 9999 9999\" value=\"4111111111111111\" onChange={() => {}} />\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default PrefilledValue;\n"
        }
      ],
      "props": {
        "maskedInputProps": {
          "mask": {
            "type": "string",
            "description": "Mask pattern. Use '9' for digit, 'a' for letter, '*' for alphanumeric, any other char as literal separator. Either mask or preset must be provided"
          },
          "preset": {
            "type": "'phone' | 'phone-us' | 'phone-intl' | 'date' | 'date-us' | 'ssn' | 'credit-card' | 'zip' | 'zip-plus4' | 'time'",
            "description": "Built-in mask preset that auto-fills the mask and a SR-readable format hint"
          },
          "formatHint": {
            "type": "string",
            "description": "Format hint string surfaced under the input and linked via aria-describedby. Auto-derived from preset when not provided"
          },
          "value": {
            "type": "string",
            "description": "Current value (raw or masked — component normalises it)"
          },
          "onChange": {
            "type": "(event: ComponentEvent<string>) => void",
            "description": "Called when the value changes"
          },
          "onRawChange": {
            "type": "(raw: string, masked: string) => void",
            "description": "Called with the raw (unmasked) value alongside the masked display value"
          },
          "slotChar": {
            "type": "string",
            "default": "_",
            "description": "Character shown for empty mask slots"
          },
          "includeLiterals": {
            "type": "boolean",
            "default": true,
            "description": "Whether to include literal separator characters in the onChange value"
          },
          "error": {
            "type": "string | boolean",
            "description": "Error message string (also marks invalid). Pass `true` to mark invalid without a visible message"
          },
          "invalid": {
            "type": "boolean",
            "description": "Force the field into an invalid state without an error message"
          },
          "helperText": {
            "type": "ReactNode",
            "description": "Helper text rendered under the input and linked via aria-describedby"
          },
          "placeholder": {
            "type": "string",
            "description": "Placeholder text. Defaults to the mask itself"
          },
          "required": {
            "type": "boolean",
            "default": false,
            "description": "Mark the input as required"
          },
          "readonly": {
            "type": "boolean",
            "default": false,
            "description": "Make the input read-only"
          },
          "disabled": {
            "type": "boolean",
            "default": false,
            "description": "Disable the input"
          },
          "autoFocus": {
            "type": "boolean",
            "default": false,
            "description": "Auto-focus on mount"
          },
          "id": {
            "type": "string",
            "description": "Unique id for the input element"
          }
        }
      },
      "storyDir": "masked-input"
    },
    "Modal": {
      "name": "Modal",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React, { useState } from 'react';\nimport { Button, Modal } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { Modal, Button } from 'fluxo-ui';\nimport { useState } from 'react';\n\nfunction MyComponent() {\n  const [isOpen, setIsOpen] = useState(false);\n\n  return (\n    <>\n      <Button onClick={() => setIsOpen(true)}>Open Modal</Button>\n\n      <Modal\n        isOpen={isOpen}\n        onClose={() => setIsOpen(false)}\n        title=\"Modal Title\"\n      >\n        <p>Modal content goes here...</p>\n\n        <div className=\"flex justify-end gap-2 mt-4\">\n          <Button onClick={() => setIsOpen(false)} layout=\"outlined\">\n            Cancel\n          </Button>\n          <Button onClick={() => setIsOpen(false)} variant=\"primary\">\n            Confirm\n          </Button>\n        </div>\n      </Modal>\n    </>\n  );\n}`;\n\nconst BasicUsage: React.FC = () => {\n    const [basicModal, setBasicModal] = useState(false);\n\n    return (\n        <>\n            <ComponentDemo title=\"Basic Modal\">\n                <Button onClick={() => setBasicModal(true)} variant=\"primary\">\n                    Open Modal\n                </Button>\n\n                <Modal isOpen={basicModal} onClose={() => setBasicModal(false)} title=\"Modal Title\">\n                    <div className=\"space-y-4\">\n                        <p className=\"text-theme-default\">\n                            This is a basic modal dialog. It contains a title, content area, and a close button.\n                        </p>\n                        <p className=\"text-theme-default\">\n                            You can close this modal by clicking the X button, pressing Escape, or clicking outside the modal.\n                        </p>\n                        <div className=\"flex justify-end gap-2 mt-6\">\n                            <Button onClick={() => setBasicModal(false)} layout=\"outlined\">\n                                Cancel\n                            </Button>\n                            <Button onClick={() => setBasicModal(false)} variant=\"primary\">\n                                Confirm\n                            </Button>\n                        </div>\n                    </div>\n                </Modal>\n            </ComponentDemo>\n\n            <div className=\"mt-4\">\n                <CodeBlock title=\"Basic Example\" code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "CustomLayout",
          "code": "import React, { useState } from 'react';\nimport { Button, Modal } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<Modal isOpen={isOpen} onClose={onClose}>\n  {/* Custom Header */}\n  <div className=\"flex items-center justify-between pb-4 border-b\">\n    <div>\n      <h2 className=\"text-2xl font-bold\">Custom Header</h2>\n      <p className=\"text-sm text-gray-500\">With subtitle</p>\n    </div>\n    <span className=\"px-3 py-1 bg-green-100 rounded-full\">Active</span>\n  </div>\n\n  {/* Content */}\n  <div className=\"py-4\">\n    <p>Your modal content here...</p>\n  </div>\n\n  {/* Custom Footer */}\n  <div className=\"flex justify-between pt-4 border-t\">\n    <Button layout=\"plain\">Skip</Button>\n    <div className=\"flex gap-2\">\n      <Button onClick={onClose} layout=\"outlined\">Cancel</Button>\n      <Button onClick={onSave} variant=\"success\">Save</Button>\n    </div>\n  </div>\n</Modal>`;\n\nconst CustomLayout: React.FC = () => {\n    const [customHeaderModal, setCustomHeaderModal] = useState(false);\n\n    return (\n        <>\n            <ComponentDemo title=\"Modal with Custom Layout\">\n                <Button onClick={() => setCustomHeaderModal(true)} variant=\"success\">\n                    Open Custom Modal\n                </Button>\n\n                <Modal isOpen={customHeaderModal} onClose={() => setCustomHeaderModal(false)}>\n                    <div className=\"space-y-6\">\n                        <div className=\"flex items-center justify-between pb-4 border-b border-theme-default\">\n                            <div>\n                                <h2 className=\"text-2xl font-bold text-theme-default\">Custom Header</h2>\n                                <p className=\"text-sm text-theme-muted\">With subtitle and custom styling</p>\n                            </div>\n                            <span className=\"px-3 py-1 bg-success-100 text-success-700 rounded-full text-sm font-medium\">\n                                Active\n                            </span>\n                        </div>\n\n                        <div className=\"space-y-4\">\n                            <p className=\"text-theme-default\">\n                                You can create completely custom headers and footers by not providing a title prop and\n                                structuring your content however you like.\n                            </p>\n                            <div className=\"bg-info-50 p-4 rounded border border-info-500/20\">\n                                <p className=\"text-sm text-info-700\">\n                                    <strong>Pro tip:</strong> Use custom layouts for complex forms, multi-step processes, or\n                                    when you need more control over the modal structure.\n                                </p>\n                            </div>\n                        </div>\n\n                        <div className=\"flex items-center justify-between pt-4 border-t border-theme-default\">\n                            <Button onClick={() => setCustomHeaderModal(false)} layout=\"plain\">\n                                Maybe later\n                            </Button>\n                            <div className=\"flex gap-2\">\n                                <Button onClick={() => setCustomHeaderModal(false)} layout=\"outlined\">\n                                    Cancel\n                                </Button>\n                                <Button onClick={() => setCustomHeaderModal(false)} variant=\"success\">\n                                    Save Changes\n                                </Button>\n                            </div>\n                        </div>\n                    </div>\n                </Modal>\n            </ComponentDemo>\n\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default CustomLayout;\n"
        },
        {
          "title": "FormExample",
          "code": "import cn from 'classnames';\nimport React from 'react';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\n\nconst code = `function FormModal() {\n  const [isOpen, setIsOpen] = useState(false);\n  const [formData, setFormData] = useState({ name: '', email: '' });\n\n  const handleSubmit = (e: React.FormEvent) => {\n    e.preventDefault();\n    console.log('Form submitted:', formData);\n    setIsOpen(false);\n  };\n\n  return (\n    <>\n      <Button onClick={() => setIsOpen(true)}>Add User</Button>\n\n      <Modal isOpen={isOpen} onClose={() => setIsOpen(false)} title=\"Add New User\">\n        <form onSubmit={handleSubmit}>\n          <div className=\"space-y-4\">\n            <div>\n              <label className=\"block text-sm font-medium mb-1\">Name</label>\n              <input\n                type=\"text\"\n                value={formData.name}\n                onChange={(e) => setFormData({ ...formData, name: e.target.value })}\n                className=\"w-full px-3 py-2 border rounded\"\n                required\n              />\n            </div>\n            <div>\n              <label className=\"block text-sm font-medium mb-1\">Email</label>\n              <input\n                type=\"email\"\n                value={formData.email}\n                onChange={(e) => setFormData({ ...formData, email: e.target.value })}\n                className=\"w-full px-3 py-2 border rounded\"\n                required\n              />\n            </div>\n          </div>\n          <div className=\"flex justify-end gap-2 mt-6\">\n            <Button type=\"button\" onClick={() => setIsOpen(false)} layout=\"outlined\">Cancel</Button>\n            <Button type=\"submit\" variant=\"primary\">Create User</Button>\n          </div>\n        </form>\n      </Modal>\n    </>\n  );\n}`;\n\nconst FormExample: React.FC = () => {\n    const { isDark } = useStoryTheme();\n\n    return (\n        <ComponentDemo title=\"Modal with Form\">\n            <div className=\"space-y-4\">\n                <p className={cn('text-sm', { 'text-gray-400': isDark, 'text-gray-500': !isDark })}>\n                    Modals work great for forms. Here's an example of how to structure a form inside a modal:\n                </p>\n                <CodeBlock code={code} />\n            </div>\n        </ComponentDemo>\n    );\n};\n\nexport default FormExample;\n"
        },
        {
          "title": "NestedModals",
          "code": "import React, { useState } from 'react';\nimport { Button, Modal } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `function MyComponent() {\n  const [firstModal, setFirstModal] = useState(false);\n  const [secondModal, setSecondModal] = useState(false);\n\n  return (\n    <>\n      <Button onClick={() => setFirstModal(true)}>Open First Modal</Button>\n\n      <Modal isOpen={firstModal} onClose={() => setFirstModal(false)} title=\"First Modal\">\n        <p>First modal content</p>\n        <Button onClick={() => setSecondModal(true)}>Open Second Modal</Button>\n      </Modal>\n\n      <Modal isOpen={secondModal} onClose={() => setSecondModal(false)} title=\"Second Modal\">\n        <p>Nested modal content</p>\n      </Modal>\n    </>\n  );\n}`;\n\nconst NestedModals: React.FC = () => {\n    const [nestedModal, setNestedModal] = useState(false);\n    const [nestedModal2, setNestedModal2] = useState(false);\n\n    return (\n        <>\n            <ComponentDemo title=\"Modal Opening Another Modal\">\n                <Button onClick={() => setNestedModal(true)} variant=\"secondary\">\n                    Open First Modal\n                </Button>\n\n                <Modal isOpen={nestedModal} onClose={() => setNestedModal(false)} title=\"First Modal\">\n                    <div className=\"space-y-4\">\n                        <p className=\"text-theme-default\">This is the first modal. You can open another modal from here.</p>\n                        <Button onClick={() => setNestedModal2(true)} variant=\"primary\">\n                            Open Second Modal\n                        </Button>\n                        <div className=\"flex justify-end mt-4\">\n                            <Button onClick={() => setNestedModal(false)} layout=\"outlined\">\n                                Close\n                            </Button>\n                        </div>\n                    </div>\n                </Modal>\n\n                <Modal isOpen={nestedModal2} onClose={() => setNestedModal2(false)} title=\"Second Modal\" size=\"sm\">\n                    <div className=\"space-y-4\">\n                        <p className=\"text-theme-default\">This is a nested modal opened from the first modal.</p>\n                        <div className=\"flex justify-end mt-4\">\n                            <Button onClick={() => setNestedModal2(false)} variant=\"primary\">\n                                Close This Modal\n                            </Button>\n                        </div>\n                    </div>\n                </Modal>\n            </ComponentDemo>\n\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default NestedModals;\n"
        },
        {
          "title": "NonClosable",
          "code": "import React, { useState } from 'react';\nimport { Button, Modal } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<Modal\n  isOpen={isOpen}\n  onClose={onClose}\n  title=\"Important Action\"\n  closeOnBackdrop={false}\n>\n  <p>This modal requires explicit action.</p>\n  <p>Clicking outside won't close it.</p>\n\n  <div className=\"flex justify-end gap-2 mt-4\">\n    <Button onClick={onClose}>Cancel</Button>\n    <Button onClick={handleConfirm} variant=\"danger\">Confirm</Button>\n  </div>\n</Modal>`;\n\nconst NonClosable: React.FC = () => {\n    const [nonClosableModal, setNonClosableModal] = useState(false);\n\n    return (\n        <>\n            <ComponentDemo title=\"Modal Without Backdrop Close\">\n                <Button onClick={() => setNonClosableModal(true)} variant=\"warning\">\n                    Open Non-closable Modal\n                </Button>\n\n                <Modal\n                    isOpen={nonClosableModal}\n                    onClose={() => setNonClosableModal(false)}\n                    title=\"Important Action\"\n                    closeOnBackdrop={false}\n                >\n                    <div className=\"space-y-4\">\n                        <p className=\"text-theme-default\">\n                            This modal cannot be closed by clicking outside of it. You must use the buttons below or press\n                            Escape.\n                        </p>\n                        <p className=\"text-theme-default\">This is useful for critical actions that require explicit user choice.</p>\n                        <div className=\"flex justify-end gap-2 mt-6\">\n                            <Button onClick={() => setNonClosableModal(false)} layout=\"outlined\">\n                                Cancel\n                            </Button>\n                            <Button onClick={() => setNonClosableModal(false)} variant=\"danger\">\n                                Delete\n                            </Button>\n                        </div>\n                    </div>\n                </Modal>\n            </ComponentDemo>\n\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default NonClosable;\n"
        },
        {
          "title": "ScrollableContent",
          "code": "import React, { useState } from 'react';\nimport { Button, Modal } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<Modal\n  isOpen={isOpen}\n  onClose={onClose}\n  title=\"Terms and Conditions\"\n  footer={\n    <div className=\"flex justify-end gap-2\">\n      <Button onClick={onClose} layout=\"outlined\">Decline</Button>\n      <Button onClick={onClose} variant=\"success\">Accept</Button>\n    </div>\n  }\n>\n  {/* Content scrolls automatically when it exceeds viewport */}\n  <p>Long content...</p>\n  <p>More content...</p>\n</Modal>`;\n\nconst ScrollableContent: React.FC = () => {\n    const [scrollableModal, setScrollableModal] = useState(false);\n\n    return (\n        <>\n            <ComponentDemo title=\"Modal with Long Content\">\n                <Button onClick={() => setScrollableModal(true)} variant=\"info\">\n                    Open Scrollable Modal\n                </Button>\n\n                <Modal\n                    isOpen={scrollableModal}\n                    onClose={() => setScrollableModal(false)}\n                    title=\"Terms and Conditions\"\n                    footer={\n                        <div className=\"flex justify-end gap-2\">\n                            <Button onClick={() => setScrollableModal(false)} layout=\"outlined\">\n                                Decline\n                            </Button>\n                            <Button onClick={() => setScrollableModal(false)} variant=\"success\">\n                                Accept\n                            </Button>\n                        </div>\n                    }\n                >\n                    <div className=\"space-y-4\">\n                        <p className=\"text-theme-default\">\n                            Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore\n                            et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris.\n                        </p>\n                        <p className=\"text-theme-default\">\n                            Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla\n                            pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit\n                            anim id est laborum.\n                        </p>\n                        <p className=\"text-theme-default\">\n                            Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium,\n                            totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae\n                            dicta sunt explicabo.\n                        </p>\n                        <p className=\"text-theme-default\">\n                            Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur\n                            magni dolores eos qui ratione voluptatem sequi nesciunt.\n                        </p>\n                        <p className=\"text-theme-default\">\n                            Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed\n                            quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.\n                        </p>\n                        <p className=\"text-theme-default\">\n                            Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut\n                            aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit\n                            esse quam nihil molestiae consequatur.\n                        </p>\n                        <p className=\"text-theme-default\">\n                            Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore\n                            et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris.\n                        </p>\n                        <p className=\"text-theme-default\">\n                            Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla\n                            pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit\n                            anim id est laborum.\n                        </p>\n                    </div>\n                </Modal>\n            </ComponentDemo>\n\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default ScrollableContent;\n"
        },
        {
          "title": "Sizes",
          "code": "import React, { useState } from 'react';\nimport { Button, Modal } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<Modal size=\"sm\" isOpen={isOpen} onClose={onClose} title=\"Small\">\n  Small modal content\n</Modal>\n\n<Modal size=\"md\" isOpen={isOpen} onClose={onClose} title=\"Medium\">\n  Medium modal content (default)\n</Modal>\n\n<Modal size=\"lg\" isOpen={isOpen} onClose={onClose} title=\"Large\">\n  Large modal content\n</Modal>\n\n<Modal size=\"xl\" isOpen={isOpen} onClose={onClose} title=\"Extra Large\">\n  Extra large modal content\n</Modal>`;\n\nconst Sizes: React.FC = () => {\n    const [smallModal, setSmallModal] = useState(false);\n    const [mediumModal, setMediumModal] = useState(false);\n    const [largeModal, setLargeModal] = useState(false);\n    const [xlModal, setXlModal] = useState(false);\n\n    return (\n        <>\n            <ComponentDemo title=\"Modal Sizes\">\n                <div className=\"flex flex-wrap gap-4\">\n                    <Button onClick={() => setSmallModal(true)} size=\"sm\">\n                        Small (sm)\n                    </Button>\n                    <Button onClick={() => setMediumModal(true)}>\n                        Medium (md)\n                    </Button>\n                    <Button onClick={() => setLargeModal(true)} size=\"lg\">\n                        Large (lg)\n                    </Button>\n                    <Button onClick={() => setXlModal(true)} size=\"lg\">\n                        Extra Large (xl)\n                    </Button>\n                </div>\n\n                <Modal isOpen={smallModal} onClose={() => setSmallModal(false)} title=\"Small Modal\" size=\"sm\">\n                    <p className=\"text-theme-default\">This is a small modal (max-width: 28rem / 448px)</p>\n                    <div className=\"flex justify-end mt-4\">\n                        <Button onClick={() => setSmallModal(false)} variant=\"primary\">\n                            Close\n                        </Button>\n                    </div>\n                </Modal>\n\n                <Modal isOpen={mediumModal} onClose={() => setMediumModal(false)} title=\"Medium Modal\">\n                    <p className=\"text-theme-default\">This is the default medium modal (max-width: 32rem / 512px)</p>\n                    <div className=\"flex justify-end mt-4\">\n                        <Button onClick={() => setMediumModal(false)} variant=\"primary\">\n                            Close\n                        </Button>\n                    </div>\n                </Modal>\n\n                <Modal isOpen={largeModal} onClose={() => setLargeModal(false)} title=\"Large Modal\" size=\"lg\">\n                    <p className=\"text-theme-default\">This is a large modal (max-width: 42rem / 672px)</p>\n                    <div className=\"flex justify-end mt-4\">\n                        <Button onClick={() => setLargeModal(false)} variant=\"primary\">\n                            Close\n                        </Button>\n                    </div>\n                </Modal>\n\n                <Modal isOpen={xlModal} onClose={() => setXlModal(false)} title=\"Extra Large Modal\" size=\"xl\">\n                    <p className=\"text-theme-default\">This is an extra large modal (max-width: 56rem / 896px)</p>\n                    <div className=\"flex justify-end mt-4\">\n                        <Button onClick={() => setXlModal(false)} variant=\"primary\">\n                            Close\n                        </Button>\n                    </div>\n                </Modal>\n            </ComponentDemo>\n\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default Sizes;\n"
        },
        {
          "title": "WithoutTitle",
          "code": "import React, { useState } from 'react';\nimport { Button, Modal } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<Modal isOpen={isOpen} onClose={onClose}>\n  <h2 className=\"text-xl font-semibold mb-4\">Custom Header</h2>\n  <p>Your custom content here...</p>\n</Modal>`;\n\nconst WithoutTitle: React.FC = () => {\n    const [noTitleModal, setNoTitleModal] = useState(false);\n\n    return (\n        <>\n            <ComponentDemo title=\"Modal Without Title\">\n                <Button onClick={() => setNoTitleModal(true)} variant=\"secondary\">\n                    Open Modal Without Title\n                </Button>\n\n                <Modal isOpen={noTitleModal} onClose={() => setNoTitleModal(false)}>\n                    <div className=\"space-y-4\">\n                        <h2 className=\"text-xl font-semibold text-theme-default\">Custom Content Header</h2>\n                        <p className=\"text-theme-default\">\n                            When no title prop is provided, the close button appears in the top-right corner,\n                            giving you full control over the modal content layout.\n                        </p>\n                        <div className=\"flex justify-end mt-4\">\n                            <Button onClick={() => setNoTitleModal(false)} variant=\"primary\">\n                                Got it\n                            </Button>\n                        </div>\n                    </div>\n                </Modal>\n            </ComponentDemo>\n\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default WithoutTitle;\n"
        }
      ],
      "props": {
        "modalProps": {
          "isOpen": {
            "type": "boolean",
            "required": true,
            "description": "Controls whether the modal is visible"
          },
          "onClose": {
            "type": "() => void",
            "required": true,
            "description": "Callback function triggered when modal should close"
          },
          "title": {
            "type": "string",
            "description": "Modal title displayed in the header. If not provided, close button appears in top-right corner"
          },
          "children": {
            "type": "React.ReactNode",
            "required": true,
            "description": "Modal content (scrollable when it overflows)"
          },
          "footer": {
            "type": "React.ReactNode",
            "description": "Footer content rendered below the scrollable area. Always visible on screen regardless of content height"
          },
          "size": {
            "type": "'sm' | 'md' | 'lg' | 'xl' | 'fullScreen'",
            "default": "'md'",
            "description": "Modal width size (sm: 28rem, md: 32rem, lg: 42rem, xl: 56rem, fullScreen: full viewport)"
          },
          "closeOnBackdrop": {
            "type": "boolean",
            "default": "true",
            "description": "Whether clicking the backdrop (overlay) closes the modal. Drag-out gestures starting inside the modal are ignored."
          },
          "initialFocus": {
            "type": "RefObject<HTMLElement>",
            "description": "Element to receive focus when the modal opens. Defaults to the first focusable element."
          },
          "ariaLabel": {
            "type": "string",
            "description": "Accessible label when no title is provided"
          }
        }
      },
      "storyDir": "modal"
    },
    "MultiStateCheckbox": {
      "name": "MultiStateCheckbox",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React, { useState } from 'react';\nimport { MultiStateCheckbox } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { basicStates } from './multi-state-checkbox-story-data';\n\nconst code = `import { MultiStateCheckbox } from 'fluxo-ui';\n\nconst states = [\n  { value: null, label: 'No Selection', icon: undefined },\n  { value: 'yes', label: 'Yes', icon: CheckIcon },\n  { value: 'no', label: 'No', icon: MinusIcon },\n];\n\nfunction MyComponent() {\n  const [value, setValue] = useState(null);\n\n  return (\n    <MultiStateCheckbox\n      items={states}\n      value={value}\n      onChange={(e) => setValue(e.value)}\n    />\n  );\n}`;\n\nconst BasicUsage: React.FC = () => {\n    const [value, setValue] = useState<string | null>(null);\n\n    return (\n        <>\n            <ComponentDemo title=\"Basic MultiStateCheckbox\">\n                <div className=\"flex flex-col gap-4\">\n                    <MultiStateCheckbox items={basicStates} value={value} onChange={(e) => setValue(e.value)} />\n                    <p className=\"text-sm text-gray-500\">\n                        Current value: <strong>{value === null ? 'null' : String(value)}</strong>\n                    </p>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock title=\"Basic Example\" code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "ControlledState",
          "code": "import React, { useState } from 'react';\nimport { Button, MultiStateCheckbox } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { basicStates } from './multi-state-checkbox-story-data';\n\nconst code = `import { MultiStateCheckbox, Button } from 'fluxo-ui';\n\nfunction MyComponent() {\n  const [value, setValue] = useState(null);\n\n  return (\n    <div>\n      <MultiStateCheckbox\n        items={states}\n        value={value}\n        onChange={(e) => setValue(e.value)}\n      />\n      <Button label=\"Reset\" onClick={() => setValue(null)} />\n      <MultiStateCheckbox\n        items={states}\n        value={value}\n        disabled\n      />\n    </div>\n  );\n}`;\n\nconst ControlledState: React.FC = () => {\n    const [value, setValue] = useState<string | null>(null);\n\n    return (\n        <>\n            <ComponentDemo title=\"Controlled & Disabled States\">\n                <div className=\"flex flex-col gap-6\">\n                    <div className=\"flex flex-col gap-2\">\n                        <span className=\"text-sm font-medium text-gray-500\">Controlled</span>\n                        <div className=\"flex items-center gap-4 flex-wrap\">\n                            <MultiStateCheckbox items={basicStates} value={value} onChange={(e) => setValue(e.value)} />\n                            <Button label=\"Reset\" variant=\"secondary\" size=\"sm\" onClick={() => setValue(null)} />\n                        </div>\n                        <p className=\"text-sm text-gray-500\">\n                            Current value: <strong>{value === null ? 'null' : String(value)}</strong>\n                        </p>\n                    </div>\n                    <div className=\"flex flex-col gap-2\">\n                        <span className=\"text-sm font-medium text-gray-500\">Disabled</span>\n                        <MultiStateCheckbox items={basicStates} value=\"yes\" disabled />\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock title=\"Controlled & Disabled Example\" code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default ControlledState;\n"
        },
        {
          "title": "CustomStates",
          "code": "import React, { useState } from 'react';\nimport { MultiStateCheckbox } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { approvalStates, priorityStates } from './multi-state-checkbox-story-data';\n\nconst code = `import { MultiStateCheckbox } from 'fluxo-ui';\nimport { InfoIcon, WarningIcon, FlagIcon, CheckIcon, MinusIcon } from 'fluxo-ui/icons';\n\nconst priorityStates = [\n  { value: null, label: 'No Priority', icon: undefined },\n  { value: 'low', label: 'Low', icon: InfoIcon },\n  { value: 'medium', label: 'Medium', icon: WarningIcon },\n  { value: 'high', label: 'High', icon: FlagIcon },\n];\n\nconst approvalStates = [\n  { value: 'pending', label: 'Pending', icon: InfoIcon },\n  { value: 'approved', label: 'Approved', icon: CheckIcon },\n  { value: 'rejected', label: 'Rejected', icon: MinusIcon },\n  { value: 'flagged', label: 'Flagged', icon: FlagIcon },\n];\n\nfunction MyComponent() {\n  const [priority, setPriority] = useState(null);\n  const [approval, setApproval] = useState('pending');\n\n  return (\n    <>\n      <MultiStateCheckbox\n        items={priorityStates}\n        value={priority}\n        onChange={(e) => setPriority(e.value)}\n      />\n      <MultiStateCheckbox\n        items={approvalStates}\n        value={approval}\n        onChange={(e) => setApproval(e.value)}\n      />\n    </>\n  );\n}`;\n\nconst CustomStates: React.FC = () => {\n    const [priority, setPriority] = useState<string | null>(null);\n    const [approval, setApproval] = useState<string>('pending');\n\n    return (\n        <>\n            <ComponentDemo title=\"Custom State Configurations\">\n                <div className=\"flex flex-col gap-6\">\n                    <div className=\"flex flex-col gap-2\">\n                        <span className=\"text-sm font-medium text-gray-500\">Priority Selector (3 states)</span>\n                        <MultiStateCheckbox items={priorityStates} value={priority} onChange={(e) => setPriority(e.value)} />\n                    </div>\n                    <div className=\"flex flex-col gap-2\">\n                        <span className=\"text-sm font-medium text-gray-500\">Approval Workflow (4 states)</span>\n                        <MultiStateCheckbox items={approvalStates} value={approval} onChange={(e) => setApproval(e.value)} />\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock title=\"Custom States Example\" code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default CustomStates;\n"
        }
      ],
      "props": {
        "multiStateCheckboxProps": {
          "items": {
            "type": "ListItem[]",
            "description": "Array of state items to cycle through. Each item has value, label, and optional icon",
            "required": true
          },
          "value": {
            "type": "any",
            "description": "Current value of the checkbox (controlled component)"
          },
          "onChange": {
            "type": "(event: ComponentEvent<T>) => void",
            "description": "Change event handler. Receives event object with value, name, and args properties"
          },
          "required": {
            "type": "boolean",
            "default": "false",
            "description": "Mark the hidden input as required for form validation"
          },
          "disabled": {
            "type": "boolean",
            "default": "false",
            "description": "Disable the checkbox interaction"
          },
          "id": {
            "type": "string",
            "description": "HTML id attribute for the button element"
          },
          "name": {
            "type": "string",
            "description": "Name attribute for the hidden input (used in forms)"
          },
          "args": {
            "type": "any",
            "description": "Additional arguments passed to onChange handler"
          },
          "className": {
            "type": "string",
            "description": "Additional CSS classes for the container"
          }
        }
      },
      "storyDir": "multi-state-checkbox"
    },
    "Multiselect": {
      "name": "Multiselect",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React, { useState } from 'react';\nimport { Multiselect as MultiselectRaw } from '../../../components';\nimport { withFieldLabel } from '../../../utils/field-label';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { frameworkOptions } from './multiselect-story-data';\n\nconst Multiselect = withFieldLabel(MultiselectRaw);\n\nconst code = `import { Multiselect } from 'fluxo-ui';\n\nfunction MyComponent() {\n  const [values, setValues] = useState(['react', 'typescript']);\n\n  const options = [\n    { label: 'React', value: 'react' },\n    { label: 'Vue.js', value: 'vue' },\n    { label: 'Angular', value: 'angular' },\n    { label: 'TypeScript', value: 'typescript' },\n    // ... more options\n  ];\n\n  return (\n    <Multiselect\n      label=\"Technologies\"\n      placeholder=\"Select technologies...\"\n      options={options}\n      value={values}\n      onChange={setValues}\n    />\n  );\n}`;\n\nconst BasicUsage: React.FC = () => {\n    const [basicValues, setBasicValues] = useState<string[]>(['react', 'typescript']);\n\n    return (\n        <>\n            <ComponentDemo title=\"Basic Multiselect\">\n                <div className=\"w-full max-w-sm\">\n                    <Multiselect\n                        label=\"Technologies\"\n                        placeholder=\"Select technologies...\"\n                        options={frameworkOptions}\n                        value={basicValues}\n                        onChange={(e) => setBasicValues(e.value)}\n                    />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock title=\"Basic Example\" code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "CustomFieldMapping",
          "code": "import React, { useState } from 'react';\nimport { Multiselect as MultiselectRaw } from '../../../components';\nimport { withFieldLabel } from '../../../utils/field-label';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { countryOptions } from './multiselect-story-data';\n\nconst Multiselect = withFieldLabel(MultiselectRaw);\n\nconst code = `const countries = [\n  { name: 'United States', code: 'US' },\n  { name: 'Canada', code: 'CA' },\n  { name: 'United Kingdom', code: 'UK' },\n  { name: 'Germany', code: 'DE' },\n];\n\n<Multiselect\n  label=\"Countries\"\n  placeholder=\"Select countries...\"\n  options={countries}\n  optionLabel=\"name\"\n  optionValue=\"code\"\n  value={values}\n  onChange={setValues}\n/>`;\n\nconst CustomFieldMapping: React.FC = () => {\n    const [customFieldValues, setCustomFieldValues] = useState<string[]>(['US', 'DE']);\n\n    return (\n        <>\n            <ComponentDemo title=\"Multiselect with optionLabel / optionValue\">\n                <div className=\"w-full max-w-sm\">\n                    <Multiselect\n                        label=\"Countries\"\n                        placeholder=\"Select countries...\"\n                        options={countryOptions}\n                        optionLabel=\"name\"\n                        optionValue=\"code\"\n                        value={customFieldValues}\n                        onChange={(e) => setCustomFieldValues(e.value)}\n                    />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default CustomFieldMapping;\n"
        },
        {
          "title": "GroupedOptions",
          "code": "import React, { useState } from 'react';\nimport { Multiselect as MultiselectRaw } from '../../../components';\nimport { withFieldLabel } from '../../../utils/field-label';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { groupedOptions } from './multiselect-story-data';\n\nconst Multiselect = withFieldLabel(MultiselectRaw);\n\nconst code = `const groupedOptions = [\n  {\n    label: 'Frontend',\n    items: [\n      { label: 'React', value: 'react' },\n      { label: 'Vue.js', value: 'vue' },\n      { label: 'Angular', value: 'angular' },\n      { label: 'Svelte', value: 'svelte' },\n    ],\n  },\n  {\n    label: 'Backend',\n    items: [\n      { label: 'Node.js', value: 'nodejs' },\n      { label: 'Django', value: 'django' },\n      { label: 'Spring Boot', value: 'spring' },\n      { label: 'Laravel', value: 'laravel' },\n    ],\n  },\n  {\n    label: 'Mobile',\n    items: [\n      { label: 'React Native', value: 'react-native' },\n      { label: 'Flutter', value: 'flutter' },\n      { label: 'Swift', value: 'swift', disabled: true },\n    ],\n  },\n];\n\n<Multiselect\n  label=\"Technologies\"\n  placeholder=\"Select technologies...\"\n  options={groupedOptions}\n  value={values}\n  onChange={setValues}\n  showSelectAll={false}\n/>`;\n\nconst GroupedOptions: React.FC = () => {\n    const [groupedValues, setGroupedValues] = useState<string[]>(['react', 'nodejs']);\n\n    return (\n        <>\n            <ComponentDemo title=\"Multiselect with Grouped Items\">\n                <div className=\"w-full max-w-sm\">\n                    <Multiselect\n                        label=\"Technologies\"\n                        placeholder=\"Select technologies...\"\n                        options={groupedOptions}\n                        value={groupedValues}\n                        onChange={(e) => setGroupedValues(e.value)}\n                        showSelectAll={false}\n                    />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default GroupedOptions;\n"
        },
        {
          "title": "MultiselectStates",
          "code": "import React from 'react';\nimport { Multiselect as MultiselectRaw } from '../../../components';\nimport { withFieldLabel } from '../../../utils/field-label';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { colorOptions } from './multiselect-story-data';\n\nconst Multiselect = withFieldLabel(MultiselectRaw);\n\nconst code = `<Multiselect label=\"Normal\" placeholder=\"Normal state\" options={options} />\n<Multiselect label=\"With Selections\" options={options} value={['red', 'blue']} onChange={setValues} />\n<Multiselect label=\"Disabled\" placeholder=\"Disabled state\" options={options} disabled />\n<Multiselect label=\"Read Only\" options={options} value={['green', 'yellow']} readonly />\n<Multiselect label=\"Required\" placeholder=\"Required field\" options={options} required />\n<Multiselect label=\"With Error\" options={options} error=\"Please select at least one option\" />`;\n\nconst MultiselectStates: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo title=\"Multiselect States\">\n                <div className=\"w-full max-w-sm space-y-4\">\n                    <Multiselect label=\"Normal\" placeholder=\"Normal state\" options={colorOptions} />\n                    <Multiselect label=\"With Selections\" options={colorOptions} value={['red', 'blue']} />\n                    <Multiselect label=\"Disabled\" placeholder=\"Disabled state\" options={colorOptions} disabled />\n                    <Multiselect label=\"Required\" placeholder=\"Required field\" options={colorOptions} required />\n                    <Multiselect\n                        label=\"With Error\"\n                        placeholder=\"Select at least one\"\n                        options={colorOptions}\n                        error=\"Please select at least one option\"\n                    />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default MultiselectStates;\n"
        },
        {
          "title": "SelectAll",
          "code": "import React, { useState } from 'react';\nimport { Multiselect as MultiselectRaw } from '../../../components';\nimport { withFieldLabel } from '../../../utils/field-label';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { skillOptions } from './multiselect-story-data';\n\nconst Multiselect = withFieldLabel(MultiselectRaw);\n\nconst code = `<Multiselect\n  label=\"Skills\"\n  placeholder=\"Select your skills...\"\n  options={skillOptions}\n  value={values}\n  onChange={setValues}\n  showSelectAll\n/>`;\n\nconst SelectAll: React.FC = () => {\n    const [selectAllValues, setSelectAllValues] = useState<string[]>([]);\n\n    return (\n        <>\n            <ComponentDemo title=\"Multiselect with Select All\">\n                <div className=\"w-full max-w-sm\">\n                    <Multiselect\n                        label=\"Skills\"\n                        placeholder=\"Select your skills...\"\n                        options={skillOptions}\n                        value={selectAllValues}\n                        onChange={(e) => setSelectAllValues(e.value)}\n                        showSelectAll\n                    />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default SelectAll;\n"
        },
        {
          "title": "SelectionLimit",
          "code": "import React, { useState } from 'react';\nimport { Multiselect as MultiselectRaw } from '../../../components';\nimport { withFieldLabel } from '../../../utils/field-label';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { colorOptions } from './multiselect-story-data';\n\nconst Multiselect = withFieldLabel(MultiselectRaw);\n\nconst code = `<Multiselect\n  label=\"Favorite Colors (Max 3)\"\n  placeholder=\"Choose up to 3 colors...\"\n  options={colorOptions}\n  value={values}\n  onChange={setValues}\n  maxSelections={3}\n/>`;\n\nconst SelectionLimit: React.FC = () => {\n    const [limitedValues, setLimitedValues] = useState<string[]>(['red', 'blue']);\n\n    return (\n        <>\n            <ComponentDemo title=\"Maximum 3 Selections\">\n                <div className=\"w-full max-w-sm\">\n                    <Multiselect\n                        label=\"Favorite Colors (Max 3)\"\n                        placeholder=\"Choose up to 3 colors...\"\n                        options={colorOptions}\n                        value={limitedValues}\n                        onChange={(e) => setLimitedValues(e.value)}\n                        maxSelections={3}\n                    />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default SelectionLimit;\n"
        },
        {
          "title": "WithoutSearch",
          "code": "import React from 'react';\nimport { Multiselect as MultiselectRaw } from '../../../components';\nimport { withFieldLabel } from '../../../utils/field-label';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { colorOptions } from './multiselect-story-data';\n\nconst Multiselect = withFieldLabel(MultiselectRaw);\n\nconst code = `<Multiselect\n  label=\"Options\"\n  placeholder=\"Select options...\"\n  options={options}\n  searchable={false}\n/>`;\n\nconst WithoutSearch: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo title=\"Non-searchable Multiselect\">\n                <div className=\"w-full max-w-sm\">\n                    <Multiselect label=\"Options\" placeholder=\"Select options...\" options={colorOptions} searchable={false} />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default WithoutSearch;\n"
        }
      ],
      "props": {
        "multiselectProps": {
          "value": {
            "type": "any[]",
            "description": "Array of currently selected values (controlled component)"
          },
          "options": {
            "type": "ListItem[] | ListItemGroup[]",
            "required": true,
            "description": "Flat array of items or grouped items. Each group has a label, optional icon, and an items array."
          },
          "onChange": {
            "type": "function",
            "description": "Change event handler called with {event, value, name, args}"
          },
          "onFilter": {
            "type": "function",
            "description": "Called when filter value changes: (query: string) => void | Promise<void>"
          },
          "placeholder": {
            "type": "string",
            "description": "Placeholder text when no options are selected"
          },
          "label": {
            "type": "string",
            "description": "Label text for the multiselect"
          },
          "error": {
            "type": "string",
            "description": "Error message to display"
          },
          "disabled": {
            "type": "boolean",
            "default": false,
            "description": "Disable the multiselect"
          },
          "readonly": {
            "type": "boolean",
            "default": false,
            "description": "Make the multiselect read-only"
          },
          "required": {
            "type": "boolean",
            "default": false,
            "description": "Mark the multiselect as required"
          },
          "searchable": {
            "type": "boolean",
            "default": true,
            "description": "Enable search/filter functionality"
          },
          "debounceMs": {
            "type": "number",
            "default": 300,
            "description": "Debounce delay in milliseconds for filter input"
          },
          "maxSelectedItems": {
            "type": "number",
            "description": "Maximum number of selections allowed"
          },
          "loading": {
            "type": "boolean",
            "default": false,
            "description": "Show loading state"
          },
          "emptyMessage": {
            "type": "string",
            "default": "No items available",
            "description": "Message to display when no options are available"
          },
          "showSelectAll": {
            "type": "boolean",
            "default": true,
            "description": "Show select all / deselect all option"
          },
          "renderItem": {
            "type": "function",
            "description": "Custom render function for items: (item, index, isSelected, isHighlighted) => ReactNode"
          },
          "renderSelectedItem": {
            "type": "function",
            "description": "Custom render function for selected items: (item, onRemove) => ReactNode"
          },
          "id": {
            "type": "string",
            "description": "HTML id attribute for the input element"
          },
          "name": {
            "type": "string",
            "description": "HTML name attribute for form submission"
          },
          "args": {
            "type": "any",
            "description": "Custom arguments passed to onChange event"
          },
          "optionLabel": {
            "type": "string",
            "default": "label",
            "description": "Property name to use as the display label from each option object"
          },
          "optionValue": {
            "type": "string",
            "default": "value",
            "description": "Property name to use as the value from each option object"
          },
          "className": {
            "type": "string",
            "description": "Additional CSS classes"
          }
        }
      },
      "storyDir": "multiselect"
    },
    "NumericInput": {
      "name": "NumericInput",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React, { useState } from 'react';\nimport { NumericInput as NumericInputRaw } from '../../../components';\nimport { withFieldLabel } from '../../../utils/field-label';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst NumericInput = withFieldLabel(NumericInputRaw);\n\nconst code = `import { NumericInput } from 'fluxo-ui';\n\nfunction MyComponent() {\n  const [value, setValue] = useState(0);\n\n  return (\n    <NumericInput\n      label=\"Quantity\"\n      value={value}\n      onChange={setValue}\n    />\n  );\n}`;\n\nconst BasicUsage: React.FC = () => {\n    const [basicValue, setBasicValue] = useState(0);\n\n    return (\n        <>\n            <ComponentDemo title=\"Basic Numeric Input\">\n                <div className=\"w-full max-w-sm\">\n                    <NumericInput label=\"Quantity\" value={basicValue} onChange={(e) => setBasicValue(e.value ?? 0)} />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock title=\"Basic Example\" code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "ClearableValue",
          "code": "import React, { useState } from 'react';\nimport { NumericInput as NumericInputRaw } from '../../../components';\nimport { withFieldLabel } from '../../../utils/field-label';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst NumericInput = withFieldLabel(NumericInputRaw);\n\nconst code = `const [value, setValue] = useState<number | undefined>(42);\n\n<NumericInput\n  label=\"Optional age\"\n  value={value}\n  onChange={(e) => setValue(e.value)}\n  placeholder=\"Leave empty if unknown\"\n/>\n\n// e.value is number when filled, undefined when cleared`;\n\nconst ClearableValue: React.FC = () => {\n    const [value, setValue] = useState<number | undefined>(42);\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Empty / Cleared State\"\n                description=\"onChange now fires with value: undefined when the field is cleared, so controlled parents can react to an empty input.\"\n            >\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16, maxWidth: 360 }}>\n                    <NumericInput\n                        label=\"Optional age\"\n                        value={value}\n                        onChange={(e) => setValue(e.value)}\n                        placeholder=\"Leave empty if unknown\"\n                    />\n                    <div\n                        style={{\n                            padding: '10px 14px',\n                            background: 'var(--eui-bg-subtle)',\n                            border: '1px solid var(--eui-border-subtle)',\n                            borderRadius: 6,\n                            fontSize: 13,\n                            color: 'var(--eui-text)',\n                        }}\n                    >\n                        Parent state:{' '}\n                        <strong>{value === undefined ? <em style={{ color: 'var(--eui-text-muted)' }}>undefined</em> : value}</strong>\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default ClearableValue;\n"
        },
        {
          "title": "DecimalPrecision",
          "code": "import React, { useState } from 'react';\nimport { NumericInput as NumericInputRaw } from '../../../components';\nimport { withFieldLabel } from '../../../utils/field-label';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst NumericInput = withFieldLabel(NumericInputRaw);\n\nconst code = `<NumericInput\n  label=\"Price ($)\"\n  value={value}\n  onChange={setValue}\n  maxDecimals={2}\n  min={0}\n/>`;\n\nconst DecimalPrecision: React.FC = () => {\n    const [decimalValue, setDecimalValue] = useState(12.34);\n\n    return (\n        <>\n            <ComponentDemo title=\"With Decimal Places\">\n                <div className=\"w-full max-w-sm\">\n                    <NumericInput\n                        label=\"Price ($)\"\n                        value={decimalValue}\n                        onChange={(e) => setDecimalValue(e.value ?? 0)}\n                        maxDecimals={2}\n                        min={0}\n                    />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default DecimalPrecision;\n"
        },
        {
          "title": "KeyboardStepping",
          "code": "import React, { useState } from 'react';\nimport { NumericInput as NumericInputRaw } from '../../../components';\nimport { withFieldLabel } from '../../../utils/field-label';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst NumericInput = withFieldLabel(NumericInputRaw);\n\nconst code = `<NumericInput\n  label=\"Volume\"\n  value={value}\n  onChange={(e) => setValue(e.value ?? 0)}\n  step={1}\n  largeStep={10}\n  min={0}\n  max={100}\n/>`;\n\nconst KeyboardStepping: React.FC = () => {\n    const [volume, setVolume] = useState(20);\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Keyboard Stepping (ArrowUp / ArrowDown)\"\n                description=\"Focus the input then press ArrowUp / ArrowDown to step by 1. Hold Shift for the larger step (10).\"\n            >\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16, maxWidth: 360 }}>\n                    <NumericInput\n                        label=\"Volume (0–100)\"\n                        value={volume}\n                        onChange={(e) => setVolume(e.value ?? 0)}\n                        step={1}\n                        largeStep={10}\n                        min={0}\n                        max={100}\n                    />\n                    <div\n                        style={{\n                            padding: '10px 14px',\n                            background: 'var(--eui-bg-subtle)',\n                            border: '1px solid var(--eui-border-subtle)',\n                            borderRadius: 6,\n                            fontSize: 13,\n                            color: 'var(--eui-text)',\n                        }}\n                    >\n                        Current value: <strong>{volume}</strong>\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default KeyboardStepping;\n"
        },
        {
          "title": "MinMaxRange",
          "code": "import React, { useState } from 'react';\nimport { NumericInput as NumericInputRaw } from '../../../components';\nimport { withFieldLabel } from '../../../utils/field-label';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst NumericInput = withFieldLabel(NumericInputRaw);\n\nconst code = `<NumericInput\n  label=\"Score (0-100)\"\n  value={value}\n  onChange={setValue}\n  min={0}\n  max={100}\n  placeholder=\"Enter score...\"\n/>`;\n\nconst MinMaxRange: React.FC = () => {\n    const [rangeValue, setRangeValue] = useState(50);\n\n    return (\n        <>\n            <ComponentDemo title=\"With Range Constraints\">\n                <div className=\"w-full max-w-sm\">\n                    <NumericInput\n                        label=\"Score (0-100)\"\n                        value={rangeValue}\n                        onChange={(e) => setRangeValue(e.value ?? 0)}\n                        min={0}\n                        max={100}\n                        placeholder=\"Enter score...\"\n                    />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default MinMaxRange;\n"
        },
        {
          "title": "NumericInputStates",
          "code": "import React, { useState } from 'react';\nimport { NumericInput as NumericInputRaw } from '../../../components';\nimport { withFieldLabel } from '../../../utils/field-label';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst NumericInput = withFieldLabel(NumericInputRaw);\n\nconst code = `<NumericInput label=\"Normal\" value={42} onChange={setValue} />\n<NumericInput label=\"Disabled\" value={42} onChange={setValue} disabled />\n<NumericInput label=\"Read Only\" value={42} readonly />\n<NumericInput label=\"With Error\" error=\"Value must be positive\" value={value} onChange={setValue} />`;\n\nconst NumericInputStates: React.FC = () => {\n    const [errorValue, setErrorValue] = useState(-5);\n    const errorMessage = errorValue < 0 ? 'Value must be positive' : undefined;\n\n    return (\n        <>\n            <ComponentDemo title=\"Input States\">\n                <div className=\"w-full max-w-sm space-y-4\">\n                    <NumericInput label=\"Normal\" value={42} onChange={() => {}} />\n                    <NumericInput label=\"Disabled\" value={42} onChange={() => {}} disabled />\n                    <NumericInput label=\"Read Only\" value={42} readonly />\n                    <NumericInput label=\"With Error\" error={errorMessage} value={errorValue} onChange={(e) => setErrorValue(e.value ?? 0)} />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default NumericInputStates;\n"
        },
        {
          "title": "Steppers",
          "code": "import React, { useState } from 'react';\nimport { NumericInput as NumericInputRaw } from '../../../components';\nimport { withFieldLabel } from '../../../utils/field-label';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst NumericInput = withFieldLabel(NumericInputRaw);\n\nconst code = `<NumericInput\n  label=\"Quantity\"\n  value={value}\n  onChange={(e) => setValue(e.value ?? 0)}\n  showSteppers\n  step={1}\n  min={0}\n  max={10}\n/>\n\n<NumericInput\n  label=\"Price\"\n  value={price}\n  onChange={(e) => setPrice(e.value ?? 0)}\n  showSteppers\n  step={0.5}\n  maxDecimals={2}\n/>`;\n\nconst Steppers: React.FC = () => {\n    const [quantity, setQuantity] = useState(1);\n    const [price, setPrice] = useState(9.5);\n\n    return (\n        <>\n            <ComponentDemo title=\"Visible Stepper Buttons\" description=\"Set showSteppers to render inline up/down buttons. The step prop controls the increment.\">\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16, maxWidth: 360 }}>\n                    <NumericInput\n                        label=\"Quantity\"\n                        value={quantity}\n                        onChange={(e) => setQuantity(e.value ?? 0)}\n                        showSteppers\n                        step={1}\n                        min={0}\n                        max={10}\n                    />\n                    <NumericInput\n                        label=\"Price ($, step 0.5)\"\n                        value={price}\n                        onChange={(e) => setPrice(e.value ?? 0)}\n                        showSteppers\n                        step={0.5}\n                        maxDecimals={2}\n                    />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default Steppers;\n"
        }
      ],
      "props": {
        "numericInputProps": {
          "value": {
            "type": "number",
            "description": "Current numeric value (controlled)"
          },
          "min": {
            "type": "number",
            "description": "Minimum allowed value"
          },
          "max": {
            "type": "number",
            "description": "Maximum allowed value"
          },
          "maxDecimals": {
            "type": "number",
            "default": 2,
            "description": "Maximum number of decimal places"
          },
          "step": {
            "type": "number",
            "default": 1,
            "description": "Increment used by ArrowUp/ArrowDown and stepper buttons"
          },
          "largeStep": {
            "type": "number",
            "description": "Increment used when Shift+ArrowUp/ArrowDown is pressed; falls back to step when not provided"
          },
          "showSteppers": {
            "type": "boolean",
            "default": false,
            "description": "Show inline up/down stepper buttons inside the input"
          },
          "placeholder": {
            "type": "string",
            "description": "Placeholder text"
          },
          "label": {
            "type": "string",
            "description": "Label text"
          },
          "error": {
            "type": "string | boolean",
            "description": "Error message string (also marks invalid). Pass `true` to mark invalid without a message"
          },
          "invalid": {
            "type": "boolean",
            "description": "Force the field into an invalid state without an error message"
          },
          "helperText": {
            "type": "ReactNode",
            "description": "Helper text rendered under the input and linked via aria-describedby"
          },
          "disabled": {
            "type": "boolean",
            "default": false,
            "description": "Disable the input"
          },
          "readonly": {
            "type": "boolean",
            "default": false,
            "description": "Make the input read-only"
          },
          "required": {
            "type": "boolean",
            "default": false,
            "description": "Mark the input as required"
          },
          "autoFocus": {
            "type": "boolean",
            "default": false,
            "description": "Auto focus the input on mount"
          },
          "id": {
            "type": "string",
            "description": "Unique identifier for the input"
          },
          "name": {
            "type": "string",
            "description": "Name attribute for the input"
          },
          "onChange": {
            "type": "function",
            "description": "Change event handler with numeric value"
          },
          "className": {
            "type": "string",
            "description": "Additional CSS classes"
          }
        }
      },
      "storyDir": "numeric-input"
    },
    "Password": {
      "name": "Password",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React, { useState } from 'react';\nimport { Password as PasswordRaw } from '../../../components';\nimport { withFieldLabel } from '../../../utils/field-label';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst Password = withFieldLabel(PasswordRaw);\n\nconst code = `import { Password } from 'fluxo-ui';\n\nfunction MyComponent() {\n  const [password, setPassword] = useState('');\n\n  return (\n    <Password\n      label=\"Password\"\n      placeholder=\"Enter your password\"\n      value={password}\n      onChange={(e) => setPassword(e.target.value)}\n    />\n  );\n}`;\n\nconst BasicUsage: React.FC = () => {\n    const [basicPassword, setBasicPassword] = useState('');\n\n    return (\n        <>\n            <ComponentDemo title=\"Basic Password Input\">\n                <div className=\"w-full max-w-sm\">\n                    <Password\n                        label=\"Password\"\n                        placeholder=\"Enter your password\"\n                        value={basicPassword}\n                        onChange={(e) => setBasicPassword(e.value)}\n                    />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock title=\"Basic Example\" code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "PasswordStates",
          "code": "import React from 'react';\nimport { Password as PasswordRaw } from '../../../components';\nimport { withFieldLabel } from '../../../utils/field-label';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst Password = withFieldLabel(PasswordRaw);\n\nconst code = `<Password\n  label=\"Normal\"\n  placeholder=\"Enter password\"\n  value={password}\n  onChange={(e) => setPassword(e.value)}\n/>\n<Password\n  label=\"Disabled\"\n  placeholder=\"Disabled\"\n  value={password}\n  onChange={(e) => setPassword(e.value)}\n  disabled\n/>`;\n\nconst PasswordStates: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo title=\"Password Input States\">\n                <div className=\"w-full max-w-sm space-y-4\">\n                    <Password label=\"Normal\" placeholder=\"Enter password\" />\n                    <Password label=\"Disabled\" placeholder=\"Disabled\" disabled />\n                    <Password label=\"Read Only\" value=\"secret123\" readonly />\n                    <Password label=\"Required\" placeholder=\"Enter password\" required />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default PasswordStates;\n"
        }
      ],
      "props": {
        "passwordProps": {
          "value": {
            "type": "string",
            "description": "Current value of the password input (controlled)"
          },
          "placeholder": {
            "type": "string",
            "description": "Placeholder text"
          },
          "label": {
            "type": "string",
            "description": "Label text"
          },
          "error": {
            "type": "string | boolean",
            "description": "Error message string (also marks invalid). Pass `true` to mark invalid without a message"
          },
          "invalid": {
            "type": "boolean",
            "description": "Force the field into an invalid state without an error message"
          },
          "helperText": {
            "type": "ReactNode",
            "description": "Helper text rendered under the input and linked via aria-describedby"
          },
          "disabled": {
            "type": "boolean",
            "default": false,
            "description": "Disable the input"
          },
          "readonly": {
            "type": "boolean",
            "default": false,
            "description": "Make the input read-only"
          },
          "required": {
            "type": "boolean",
            "default": false,
            "description": "Mark the input as required"
          },
          "toggleable": {
            "type": "boolean",
            "default": true,
            "description": "Show password visibility toggle button"
          },
          "showPassword": {
            "type": "boolean",
            "description": "Controlled password visibility state"
          },
          "maxLength": {
            "type": "number",
            "description": "Maximum character limit"
          },
          "minLength": {
            "type": "number",
            "description": "Minimum character requirement"
          },
          "autoComplete": {
            "type": "string",
            "default": "current-password",
            "description": "Auto-complete hint"
          },
          "autoFocus": {
            "type": "boolean",
            "default": false,
            "description": "Auto focus the input on mount"
          },
          "id": {
            "type": "string",
            "description": "Unique identifier for the input"
          },
          "name": {
            "type": "string",
            "description": "Name attribute for the input"
          },
          "onChange": {
            "type": "function",
            "description": "Change event handler"
          },
          "className": {
            "type": "string",
            "description": "Additional CSS classes"
          },
          "strengthMeter": {
            "type": "boolean | PasswordStrengthMeterProps",
            "description": "When truthy, render a PasswordStrengthMeter wired to the input value. Pass props (without value) to configure rules, allowed characters, thresholds, custom rules, and meter style"
          }
        }
      },
      "storyDir": "password"
    },
    "Popover": {
      "name": "Popover",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React, { useRef, useState } from 'react';\nimport { Button, Popover } from '../../../components';\nimport { ListItem } from '../../../types';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { fruitItems } from './popover-story-data';\n\nconst code = `const [isOpen, setIsOpen] = useState(false);\nconst [selected, setSelected] = useState<ListItem | null>(null);\nconst triggerRef = useRef<HTMLButtonElement>(null);\n\n<Button ref={triggerRef} onClick={() => setIsOpen(!isOpen)}>\n  {selected ? selected.label : 'Pick a fruit'}\n</Button>\n\n<Popover\n  isOpen={isOpen}\n  onClose={() => setIsOpen(false)}\n  triggerElement={triggerRef.current}\n  items={fruitItems}\n  onSelect={(item) => {\n    setSelected(item);\n    setIsOpen(false);\n  }}\n  selectedIndex={fruitItems.findIndex(\n    (i) => i.value === selected?.value\n  )}\n/>`;\n\nconst BasicUsage: React.FC = () => {\n    const [isOpen, setIsOpen] = useState(false);\n    const [selected, setSelected] = useState<ListItem | null>(null);\n    const triggerRef = useRef<HTMLButtonElement>(null);\n\n    return (\n        <>\n            <ComponentDemo title=\"Simple popover with selectable items\" description=\"Click the button to open a popover list and select an item.\">\n                <div className=\"flex flex-col items-center gap-3\">\n                    <span ref={triggerRef}>\n                        <Button onClick={() => setIsOpen(!isOpen)}>\n                            {selected ? selected.label : 'Pick a fruit'}\n                        </Button>\n                    </span>\n                    <Popover\n                        isOpen={isOpen}\n                        onClose={() => setIsOpen(false)}\n                        triggerElement={triggerRef.current}\n                        items={fruitItems}\n                        onSelect={(item) => {\n                            setSelected(item);\n                            setIsOpen(false);\n                        }}\n                        selectedIndex={fruitItems.findIndex((i) => i.value === selected?.value)}\n                    />\n                    {selected && <span className=\"text-sm opacity-70\">Selected: {selected.label}</span>}\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "ControlledPopover",
          "code": "import React, { useRef, useState } from 'react';\nimport { Button, Popover } from '../../../components';\nimport { ListItem } from '../../../types';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { colorItems } from './popover-story-data';\n\nconst code = `const [isOpen, setIsOpen] = useState(false);\nconst triggerRef = useRef<HTMLButtonElement>(null);\n\n<div className=\"flex gap-3\">\n  <Button ref={triggerRef} onClick={() => setIsOpen(true)}>\n    Open Popover\n  </Button>\n  <Button variant=\"danger\" layout=\"outlined\"\n    onClick={() => setIsOpen(false)}>\n    Close Popover\n  </Button>\n</div>\n\n<Popover\n  isOpen={isOpen}\n  onClose={() => setIsOpen(false)}\n  triggerElement={triggerRef.current}\n  items={colorItems}\n  onSelect={(item) => {\n    setSelected(item);\n    setIsOpen(false);\n  }}\n/>`;\n\nconst ControlledPopover: React.FC = () => {\n    const [isOpen, setIsOpen] = useState(false);\n    const [selected, setSelected] = useState<ListItem | null>(null);\n    const triggerRef = useRef<HTMLSpanElement>(null);\n\n    return (\n        <>\n            <ComponentDemo title=\"Controlled open and close\" description=\"Programmatically control the popover with separate open and close buttons.\">\n                <div className=\"flex flex-col items-center gap-3\">\n                    <div className=\"flex gap-3\">\n                        <span ref={triggerRef}>\n                            <Button variant=\"primary\" onClick={() => setIsOpen(true)}>\n                                Open Popover\n                            </Button>\n                        </span>\n                        <Button variant=\"danger\" layout=\"outlined\" onClick={() => setIsOpen(false)}>\n                            Close Popover\n                        </Button>\n                    </div>\n                    <Popover\n                        isOpen={isOpen}\n                        onClose={() => setIsOpen(false)}\n                        triggerElement={triggerRef.current}\n                        items={colorItems}\n                        onSelect={(item) => {\n                            setSelected(item);\n                            setIsOpen(false);\n                        }}\n                        selectedIndex={colorItems.findIndex((i) => i.value === selected?.value)}\n                    />\n                    {selected && <span className=\"text-sm opacity-70\">Selected: {selected.label}</span>}\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default ControlledPopover;\n"
        },
        {
          "title": "CustomContent",
          "code": "import React, { useRef, useState } from 'react';\nimport { Button, Popover } from '../../../components';\nimport { ListItem } from '../../../types';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst statusItems: ListItem[] = [\n    { label: 'Online', value: 'online' },\n    { label: 'Away', value: 'away' },\n    { label: 'Busy', value: 'busy' },\n    { label: 'Offline', value: 'offline' },\n];\n\nconst statusColors: Record<string, string> = {\n    online: '#22c55e',\n    away: '#eab308',\n    busy: '#ef4444',\n    offline: '#6b7280',\n};\n\nconst code = `const renderItem = (item, index, isSelected, isHighlighted) => (\n  <div\n    className={cn('eui-popover-item', {\n      'eui-popover-item-highlighted': isHighlighted,\n      'eui-popover-item-selected': isSelected,\n    })}\n    onClick={() => handleSelect(item, index)}\n    onMouseEnter={() => setHighlighted(index)}\n  >\n    <span\n      style={{\n        width: 8, height: 8,\n        borderRadius: '50%',\n        backgroundColor: statusColors[item.value],\n      }}\n    />\n    <span>{item.label}</span>\n  </div>\n);\n\n<Popover\n  isOpen={isOpen}\n  onClose={() => setIsOpen(false)}\n  triggerElement={triggerRef.current}\n  items={statusItems}\n  onSelect={handleSelect}\n  renderItem={renderItem}\n  width=\"180px\"\n/>`;\n\nconst CustomContent: React.FC = () => {\n    const [isOpen, setIsOpen] = useState(false);\n    const [selected, setSelected] = useState<ListItem>(statusItems[0]);\n    const triggerRef = useRef<HTMLSpanElement>(null);\n\n    return (\n        <>\n            <ComponentDemo title=\"Custom renderItem\" description=\"Use the renderItem prop to fully customize how each list item is rendered.\">\n                <div className=\"flex flex-col items-center gap-3\">\n                    <span ref={triggerRef}>\n                        <Button onClick={() => setIsOpen(!isOpen)}>\n                            <span className=\"flex items-center gap-2\">\n                                <span\n                                    style={{\n                                        width: 8,\n                                        height: 8,\n                                        borderRadius: '50%',\n                                        backgroundColor: statusColors[selected.value],\n                                        display: 'inline-block',\n                                    }}\n                                />\n                                {selected.label}\n                            </span>\n                        </Button>\n                    </span>\n                    <Popover\n                        isOpen={isOpen}\n                        onClose={() => setIsOpen(false)}\n                        triggerElement={triggerRef.current}\n                        items={statusItems}\n                        onSelect={(item) => {\n                            setSelected(item);\n                            setIsOpen(false);\n                        }}\n                        selectedIndex={statusItems.findIndex((i) => i.value === selected.value)}\n                        renderItem={(item, _index, isSelected, isHighlighted) => (\n                            <div\n                                className={`eui-popover-item${isHighlighted ? ' eui-popover-item-highlighted' : ''}${isSelected ? ' eui-popover-item-selected' : ''}`}\n                                onClick={() => {\n                                    setSelected(item);\n                                    setIsOpen(false);\n                                }}\n                            >\n                                <span\n                                    style={{\n                                        width: 8,\n                                        height: 8,\n                                        borderRadius: '50%',\n                                        backgroundColor: statusColors[item.value],\n                                        display: 'inline-block',\n                                        flexShrink: 0,\n                                    }}\n                                />\n                                <span className=\"eui-popover-item-label\">{item.label}</span>\n                            </div>\n                        )}\n                        width=\"180px\"\n                    />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default CustomContent;\n"
        },
        {
          "title": "FilterablePopover",
          "code": "import React, { useRef, useState } from 'react';\nimport { Button, Popover, TextInput } from '../../../components';\nimport { ListItem } from '../../../types';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { fruitItems } from './popover-story-data';\n\nconst code = `const [filter, setFilter] = useState('');\n\n<Popover\n  isOpen={isOpen}\n  onClose={() => setIsOpen(false)}\n  triggerElement={triggerRef.current}\n  items={fruitItems}\n  filter={filter}\n  onSelect={(item) => {\n    setSelected(item);\n    setIsOpen(false);\n  }}\n  emptyMessage=\"No fruits match your search\"\n>\n  <div style={{ padding: '8px' }}>\n    <TextInput\n      value={filter}\n      onChange={setFilter}\n      placeholder=\"Search fruits...\"\n    />\n  </div>\n</Popover>`;\n\nconst FilterablePopover: React.FC = () => {\n    const [isOpen, setIsOpen] = useState(false);\n    const [selected, setSelected] = useState<ListItem | null>(null);\n    const [filter, setFilter] = useState('');\n    const triggerRef = useRef<HTMLSpanElement>(null);\n\n    const handleClose = () => {\n        setIsOpen(false);\n        setFilter('');\n    };\n\n    return (\n        <>\n            <ComponentDemo title=\"Filterable popover with children\" description=\"Use the filter prop alongside children to render a search input above the list.\">\n                <div className=\"flex flex-col items-center gap-3\">\n                    <span ref={triggerRef}>\n                        <Button variant=\"primary\" layout=\"outlined\" onClick={() => setIsOpen(!isOpen)}>\n                            {selected ? selected.label : 'Search & select'}\n                        </Button>\n                    </span>\n                    <Popover\n                        isOpen={isOpen}\n                        onClose={handleClose}\n                        triggerElement={triggerRef.current}\n                        items={fruitItems}\n                        filter={filter}\n                        onSelect={(item) => {\n                            setSelected(item);\n                            handleClose();\n                        }}\n                        selectedIndex={fruitItems.findIndex((i) => i.value === selected?.value)}\n                        emptyMessage=\"No fruits match your search\"\n                        width=\"220px\"\n                    >\n                        <div style={{ padding: '8px 8px 0' }}>\n                            <TextInput value={filter} onChange={(e: any) => setFilter(e.value || e)} placeholder=\"Search fruits...\" />\n                        </div>\n                    </Popover>\n                    {selected && <span className=\"text-sm opacity-70\">Selected: {selected.label}</span>}\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default FilterablePopover;\n"
        },
        {
          "title": "GroupedItems",
          "code": "import React, { useRef, useState } from 'react';\nimport { Button, Popover } from '../../../components';\nimport { ListItem } from '../../../types';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { allGroupItems, groupedItems } from './popover-story-data';\n\nconst code = `const groups = [\n  {\n    label: 'Fruits',\n    items: [\n      { label: 'Apple', value: 'apple' },\n      { label: 'Banana', value: 'banana' },\n    ],\n  },\n  {\n    label: 'Vegetables',\n    items: [\n      { label: 'Carrot', value: 'carrot' },\n      { label: 'Broccoli', value: 'broccoli' },\n    ],\n  },\n];\n\n<Popover\n  isOpen={isOpen}\n  onClose={() => setIsOpen(false)}\n  triggerElement={triggerRef.current}\n  items={allItems}\n  groups={groups}\n  onSelect={(item) => {\n    setSelected(item);\n    setIsOpen(false);\n  }}\n/>`;\n\nconst GroupedItems: React.FC = () => {\n    const [isOpen, setIsOpen] = useState(false);\n    const [selected, setSelected] = useState<ListItem | null>(null);\n    const triggerRef = useRef<HTMLSpanElement>(null);\n\n    return (\n        <>\n            <ComponentDemo title=\"Grouped list items\" description=\"Items organized into labeled groups with section headers.\">\n                <div className=\"flex flex-col items-center gap-3\">\n                    <span ref={triggerRef}>\n                        <Button variant=\"primary\" onClick={() => setIsOpen(!isOpen)}>\n                            {selected ? selected.label : 'Select category item'}\n                        </Button>\n                    </span>\n                    <Popover\n                        isOpen={isOpen}\n                        onClose={() => setIsOpen(false)}\n                        triggerElement={triggerRef.current}\n                        items={allGroupItems}\n                        groups={groupedItems}\n                        onSelect={(item) => {\n                            setSelected(item);\n                            setIsOpen(false);\n                        }}\n                        selectedIndex={allGroupItems.findIndex((i) => i.value === selected?.value)}\n                    />\n                    {selected && <span className=\"text-sm opacity-70\">Selected: {selected.label}</span>}\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default GroupedItems;\n"
        }
      ],
      "props": {
        "popoverProps": {
          "isOpen": {
            "type": "boolean",
            "required": true,
            "description": "Controls whether the popover is visible."
          },
          "onClose": {
            "type": "(e?: MouseEvent) => void",
            "required": true,
            "description": "Callback invoked when the popover should close (click outside, Escape key)."
          },
          "triggerElement": {
            "type": "HTMLElement | null",
            "required": true,
            "description": "The DOM element the popover is anchored to for positioning."
          },
          "items": {
            "type": "ListItem[]",
            "required": true,
            "description": "Array of list items to display inside the popover."
          },
          "groups": {
            "type": "ListItemGroup[]",
            "description": "Optional grouping of items with labeled section headers."
          },
          "onSelect": {
            "type": "(item: ListItem, index: number) => void",
            "required": true,
            "description": "Callback invoked when an item is selected."
          },
          "selectedIndex": {
            "type": "number",
            "default": "-1",
            "description": "Index of the currently selected item (shows a check mark)."
          },
          "renderItem": {
            "type": "(item, index, isSelected, isHighlighted) => ReactNode",
            "description": "Custom render function for each list item."
          },
          "maxHeight": {
            "type": "string",
            "default": "'300px'",
            "description": "Maximum height of the popover container before scrolling."
          },
          "width": {
            "type": "string",
            "description": "Width of the popover. Defaults to the trigger element's width."
          },
          "filter": {
            "type": "string",
            "default": "''",
            "description": "Filter string to narrow down displayed items by label."
          },
          "loading": {
            "type": "boolean",
            "default": "false",
            "description": "Shows a loading spinner instead of items."
          },
          "emptyMessage": {
            "type": "string",
            "default": "'No items found'",
            "description": "Message displayed when no items match the filter."
          },
          "children": {
            "type": "ReactNode",
            "description": "Content rendered above the item list (e.g., a search input)."
          }
        }
      },
      "storyDir": "popover"
    },
    "ProgressBar": {
      "name": "ProgressBar",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React from 'react';\nimport { ProgressBar } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { ProgressBar } from 'fluxo-ui';\n\nfunction MyComponent() {\n  return (\n    <div className=\"space-y-4\">\n      <ProgressBar value={25} />\n      <ProgressBar value={50} />\n      <ProgressBar value={75} />\n      <ProgressBar value={100} />\n    </div>\n  );\n}`;\n\nconst BasicUsage: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Basic Progress Bar\" description=\"Simple progress bars with different values\" centered={false}>\n            <div className=\"space-y-6 w-full p-2\">\n                <ProgressBar value={25} />\n                <ProgressBar value={50} />\n                <ProgressBar value={75} />\n                <ProgressBar value={100} />\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default BasicUsage;\n"
        },
        {
          "title": "BufferProgress",
          "code": "import React, { useEffect, useState } from 'react';\nimport { ProgressBar } from '../../../components';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst BufferProgress: React.FC = () => {\n    const [value, setValue] = useState(0);\n\n    useEffect(() => {\n        const interval = setInterval(() => {\n            setValue((prev) => (prev >= 100 ? 0 : prev + 2));\n        }, 100);\n        return () => clearInterval(interval);\n    }, []);\n\n    return (\n        <ComponentDemo title=\"Buffered Progress\" description=\"Progress with buffer indicator for streaming content\" centered={false}>\n            <div className=\"space-y-5 w-full p-2\">\n                <ProgressBar value={35} buffer={60} showValue label=\"Video Playback\" variant=\"info\" />\n                <ProgressBar value={value} buffer={Math.min(value + 20, 100)} showValue label=\"Streaming\" variant=\"primary\" layout=\"rounded\" />\n            </div>\n        </ComponentDemo>\n    );\n};\n\nexport default BufferProgress;\n"
        },
        {
          "title": "DynamicProgress",
          "code": "import React, { useEffect, useState } from 'react';\nimport { ProgressBar } from '../../../components';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst DynamicProgress: React.FC = () => {\n    const [value, setValue] = useState(0);\n\n    useEffect(() => {\n        const interval = setInterval(() => {\n            setValue((prev) => (prev >= 100 ? 0 : prev + 2));\n        }, 100);\n        return () => clearInterval(interval);\n    }, []);\n\n    return (\n        <ComponentDemo title=\"Animated Progress\" description=\"Live updating progress bar\" centered={false}>\n            <div className=\"space-y-5 w-full p-2\">\n                <ProgressBar value={value} showValue label=\"Uploading...\" variant=\"primary\" layout=\"animated\" size=\"lg\" />\n                <ProgressBar value={value} showValue label=\"Compiling...\" variant=\"success\" layout=\"rounded\" />\n            </div>\n        </ComponentDemo>\n    );\n};\n\nexport default DynamicProgress;\n"
        },
        {
          "title": "Indeterminate",
          "code": "import React from 'react';\nimport { ProgressBar } from '../../../components';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst Indeterminate: React.FC = () => (\n    <ComponentDemo title=\"Indeterminate Mode\" description=\"For when progress duration is unknown\" centered={false}>\n        <div className=\"space-y-5 w-full p-2\">\n            <ProgressBar value={0} indeterminate variant=\"primary\" label=\"Loading data...\" />\n            <ProgressBar value={0} indeterminate variant=\"info\" label=\"Processing...\" size=\"sm\" />\n            <ProgressBar value={0} indeterminate variant=\"success\" label=\"Syncing...\" layout=\"rounded\" />\n        </div>\n    </ComponentDemo>\n);\n\nexport default Indeterminate;\n"
        },
        {
          "title": "LabelsAndValues",
          "code": "import React from 'react';\nimport { ProgressBar } from '../../../components';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst LabelsAndValues: React.FC = () => (\n    <ComponentDemo title=\"Labels & Custom Templates\" description=\"Progress bars with labels and custom value templates\" centered={false}>\n        <div className=\"space-y-5 w-full p-2\">\n            <ProgressBar value={45} showValue label=\"Default Value\" />\n            <ProgressBar value={750} max={1000} showValue valueTemplate=\"{value} / {max} MB\" label=\"Storage Used\" sublabel=\"Free tier\" />\n            <ProgressBar value={3} max={5} showValue valueTemplate={(v, m) => <span><strong>{v}</strong> of {m} tasks</span>} label=\"Tasks Completed\" />\n            <ProgressBar value={88} showValue valueTemplate=\"{percent}% complete\" label=\"Project Alpha\" variant=\"success\" />\n        </div>\n    </ComponentDemo>\n);\n\nexport default LabelsAndValues;\n"
        },
        {
          "title": "Layouts",
          "code": "import React from 'react';\nimport { ProgressBar } from '../../../components';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst Layouts: React.FC = () => (\n    <ComponentDemo title=\"Layout Styles\" description=\"Different visual styles for the progress bar\" centered={false}>\n        <div className=\"space-y-5 w-full p-2\">\n            <ProgressBar value={65} layout=\"default\" showValue label=\"Default\" />\n            <ProgressBar value={65} layout=\"rounded\" showValue label=\"Rounded\" />\n            <ProgressBar value={65} layout=\"sharp\" showValue label=\"Sharp\" />\n            <ProgressBar value={65} layout=\"striped\" showValue label=\"Striped\" />\n            <ProgressBar value={65} layout=\"animated\" showValue label=\"Animated Striped\" />\n        </div>\n    </ComponentDemo>\n);\n\nexport default Layouts;\n"
        },
        {
          "title": "MultiSegment",
          "code": "import React from 'react';\nimport { ProgressBar } from '../../../components';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst MultiSegment: React.FC = () => (\n    <ComponentDemo title=\"Multi-Segment Progress\" description=\"Stacked segments representing multiple values\" centered={false}>\n        <div className=\"space-y-5 w-full p-2\">\n            <ProgressBar\n                value={0}\n                multipleValues={[\n                    { value: 35, variant: 'success', label: 'Passed' },\n                    { value: 15, variant: 'warning', label: 'Pending' },\n                    { value: 10, variant: 'danger', label: 'Failed' },\n                ]}\n                label=\"Test Results\"\n                showValue\n                valueTemplate=\"60 / 100 tests\"\n                size=\"lg\"\n            />\n            <ProgressBar\n                value={0}\n                multipleValues={[\n                    { value: 40, variant: 'primary', label: 'Used' },\n                    { value: 20, variant: 'info', label: 'Cached' },\n                ]}\n                label=\"Disk Space\"\n                showValue\n                valueTemplate=\"60 GB / 100 GB\"\n                layout=\"rounded\"\n            />\n        </div>\n    </ComponentDemo>\n);\n\nexport default MultiSegment;\n"
        },
        {
          "title": "Sizes",
          "code": "import React from 'react';\nimport { ProgressBar } from '../../../components';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst Sizes: React.FC = () => (\n    <ComponentDemo title=\"Size Options\" description=\"Five size options from extra small to extra large\" centered={false}>\n        <div className=\"space-y-5 w-full p-2\">\n            <ProgressBar value={60} size=\"xs\" showValue label=\"Extra Small\" />\n            <ProgressBar value={60} size=\"sm\" showValue label=\"Small\" />\n            <ProgressBar value={60} size=\"md\" showValue label=\"Medium\" />\n            <ProgressBar value={60} size=\"lg\" showValue label=\"Large\" />\n            <ProgressBar value={60} size=\"xl\" showValue label=\"Extra Large\" />\n        </div>\n    </ComponentDemo>\n);\n\nexport default Sizes;\n"
        },
        {
          "title": "Variants",
          "code": "import React from 'react';\nimport { ProgressBar } from '../../../components';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst Variants: React.FC = () => (\n    <ComponentDemo title=\"Color Variants\" description=\"All available color variants\" centered={false}>\n        <div className=\"space-y-5 w-full p-2\">\n            <ProgressBar value={70} variant=\"default\" showValue label=\"Default\" />\n            <ProgressBar value={70} variant=\"primary\" showValue label=\"Primary\" />\n            <ProgressBar value={70} variant=\"success\" showValue label=\"Success\" />\n            <ProgressBar value={70} variant=\"warning\" showValue label=\"Warning\" />\n            <ProgressBar value={70} variant=\"danger\" showValue label=\"Danger\" />\n            <ProgressBar value={70} variant=\"info\" showValue label=\"Info\" />\n        </div>\n    </ComponentDemo>\n);\n\nexport default Variants;\n"
        }
      ],
      "props": {
        "progressBarProps": {
          "value": {
            "type": "number",
            "description": "Current progress value",
            "default": "-"
          },
          "max": {
            "type": "number",
            "default": "100",
            "description": "Maximum value"
          },
          "min": {
            "type": "number",
            "default": "0",
            "description": "Minimum value"
          },
          "variant": {
            "type": "'default' | 'primary' | 'success' | 'warning' | 'danger' | 'info'",
            "default": "'primary'",
            "description": "Color variant"
          },
          "size": {
            "type": "'xs' | 'sm' | 'md' | 'lg' | 'xl'",
            "default": "'md'",
            "description": "Bar height/text size"
          },
          "layout": {
            "type": "'default' | 'rounded' | 'sharp' | 'striped' | 'animated'",
            "default": "'default'",
            "description": "Visual layout style"
          },
          "showValue": {
            "type": "boolean",
            "default": "false",
            "description": "Show the progress value text"
          },
          "valueTemplate": {
            "type": "string | ((value, max) => ReactNode)",
            "description": "Custom value display. Use {value}, {max}, {percent} placeholders or a render function"
          },
          "label": {
            "type": "ReactNode",
            "description": "Label displayed above the bar"
          },
          "sublabel": {
            "type": "ReactNode",
            "description": "Secondary label next to the label"
          },
          "indeterminate": {
            "type": "boolean",
            "default": "false",
            "description": "Show indeterminate animation"
          },
          "buffer": {
            "type": "number",
            "description": "Buffer value for buffered progress display"
          },
          "multipleValues": {
            "type": "ProgressBarSegment[]",
            "description": "Array of segments for stacked progress"
          },
          "className": {
            "type": "string",
            "description": "Additional CSS class"
          },
          "disabled": {
            "type": "boolean",
            "default": "false",
            "description": "Disabled state with reduced opacity"
          },
          "ariaLabel": {
            "type": "string",
            "description": "Accessible label"
          },
          "id": {
            "type": "string",
            "description": "HTML id attribute"
          }
        }
      },
      "storyDir": "progress-bar"
    },
    "RadioButton": {
      "name": "RadioButton",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React, { useState } from 'react';\nimport { RadioButtonGroup as RadioButtonGroupRaw } from '../../../components';\nimport { withFieldLabel } from '../../../utils/field-label';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { basicOptions } from './radio-button-story-data';\n\nconst RadioButtonGroup = withFieldLabel(RadioButtonGroupRaw);\n\nconst BasicUsage: React.FC = () => {\n    const [basicValue, setBasicValue] = useState('option2');\n\n    return (\n        <>\n            <ComponentDemo title=\"Basic Radio Button Group\">\n                <div className=\"max-w-xs\">\n                    <RadioButtonGroup\n                        label=\"Choose an option\"\n                        items={basicOptions}\n                        value={basicValue}\n                        onChange={(e) => setBasicValue(e.value)}\n                    />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock\n                    title=\"Basic Example\"\n                    code={`import { RadioButtonGroup } from 'fluxo-ui';\n\nfunction MyComponent() {\n  const [value, setValue] = useState('option2');\n\n  const options = [\n    { label: 'Option 1', value: 'option1' },\n    { label: 'Option 2', value: 'option2' },\n    { label: 'Option 3', value: 'option3' },\n    { label: 'Disabled Option', value: 'disabled', disabled: true }\n  ];\n\n  return (\n    <RadioButtonGroup\n      label=\"Choose an option\"\n      items={options}\n      value={value}\n      onChange={setValue}\n    />\n  );\n}`}\n                />\n            </div>\n        </>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "ControlledUncontrolled",
          "code": "import cn from 'classnames';\nimport React, { useState } from 'react';\nimport { RadioButtonGroup as RadioButtonGroupRaw } from '../../../components';\nimport { withFieldLabel } from '../../../utils/field-label';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\nimport { priorityOptions } from './radio-button-story-data';\n\nconst RadioButtonGroup = withFieldLabel(RadioButtonGroupRaw);\n\nconst ControlledUncontrolled: React.FC = () => {\n    const { isDark } = useStoryTheme();\n    const [horizontalValue, setHorizontalValue] = useState('medium');\n\n    return (\n        <>\n            <ComponentDemo title=\"Controlled vs Uncontrolled\">\n                <div className=\"grid grid-cols-1 md:grid-cols-2 gap-8\">\n                    <div>\n                        <h4 className={cn('mb-3', { 'text-gray-100': isDark, 'text-gray-900': !isDark })}>Controlled (with state)</h4>\n                        <RadioButtonGroup\n                            items={priorityOptions}\n                            value={horizontalValue}\n                            onChange={(e) => setHorizontalValue(e.value)}\n                        />\n                        <p className={cn('text-sm mt-2', { 'text-gray-400': isDark, 'text-gray-600': !isDark })}>Selected: {horizontalValue}</p>\n                    </div>\n                    <div>\n                        <h4 className={cn('mb-3', { 'text-gray-100': isDark, 'text-gray-900': !isDark })}>Uncontrolled (default value)</h4>\n                        <RadioButtonGroup items={priorityOptions} value=\"high\" />\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock\n                    code={`// Controlled\nconst [value, setValue] = useState('medium');\n\n<RadioButtonGroup\n  items={options}\n  value={value}\n  onChange={setValue}\n/>\n\n// Uncontrolled\n<RadioButtonGroup\n  items={options}\n  value=\"high\"\n/>`}\n                />\n            </div>\n        </>\n    );\n};\n\nexport default ControlledUncontrolled;\n"
        },
        {
          "title": "HorizontalLayout",
          "code": "import React, { useState } from 'react';\nimport { RadioButtonGroup as RadioButtonGroupRaw } from '../../../components';\nimport { withFieldLabel } from '../../../utils/field-label';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { priorityOptions } from './radio-button-story-data';\n\nconst RadioButtonGroup = withFieldLabel(RadioButtonGroupRaw);\n\nconst HorizontalLayout: React.FC = () => {\n    const [horizontalValue, setHorizontalValue] = useState('medium');\n\n    return (\n        <>\n            <ComponentDemo title=\"Horizontal Radio Group\">\n                <div className=\"max-w-md\">\n                    <RadioButtonGroup\n                        label=\"Priority Level\"\n                        items={priorityOptions}\n                        value={horizontalValue}\n                        onChange={(e) => setHorizontalValue(e.value)}\n                        orientation=\"horizontal\"\n                    />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock\n                    code={`const priorityOptions = [\n  { label: 'Low', value: 'low' },\n  { label: 'Medium', value: 'medium' },\n  { label: 'High', value: 'high' }\n];\n\n<RadioButtonGroup\n  label=\"Priority Level\"\n  items={priorityOptions}\n  value={value}\n  onChange={setValue}\n  orientation=\"horizontal\"\n/>`}\n                />\n            </div>\n        </>\n    );\n};\n\nexport default HorizontalLayout;\n"
        },
        {
          "title": "States",
          "code": "import React from 'react';\nimport { RadioButtonGroup as RadioButtonGroupRaw } from '../../../components';\nimport { withFieldLabel } from '../../../utils/field-label';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { priorityOptions } from './radio-button-story-data';\n\nconst RadioButtonGroup = withFieldLabel(RadioButtonGroupRaw);\n\nconst States: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo title=\"Radio Button States\">\n                <div className=\"grid grid-cols-1 md:grid-cols-2 gap-8\">\n                    <RadioButtonGroup label=\"Normal State\" items={priorityOptions} value=\"medium\" />\n                    <RadioButtonGroup label=\"Disabled State\" items={priorityOptions} value=\"low\" disabled />\n                    <RadioButtonGroup label=\"Required Field\" items={priorityOptions} />\n                    <RadioButtonGroup label=\"With Error\" items={priorityOptions} error=\"Please select an option\" />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock\n                    code={`<RadioButtonGroup\n  label=\"Normal State\"\n  items={options}\n  value=\"md\"\n/>\n<RadioButtonGroup\n  label=\"Disabled State\"\n  items={options}\n  value=\"low\"\n  disabled\n/>\n<RadioButtonGroup\n  label=\"Required Field\"\n  items={options}\n  required\n/>\n<RadioButtonGroup\n  label=\"With Error\"\n  items={options}\n  error=\"Please select an option\"\n/>`}\n                />\n            </div>\n        </>\n    );\n};\n\nexport default States;\n"
        }
      ],
      "props": {
        "radioButtonGroupProps": {
          "items": {
            "type": "ListItem[]",
            "required": true,
            "description": "Array of radio button items with label, value, and optional disabled property"
          },
          "value": {
            "type": "string",
            "description": "Currently selected value (controlled component)"
          },
          "onChange": {
            "type": "function",
            "description": "Change event handler - receives ComponentEvent with selected value"
          },
          "name": {
            "type": "string",
            "description": "Name attribute for the radio group"
          },
          "args": {
            "type": "any",
            "description": "Custom arguments passed through to onChange event"
          },
          "label": {
            "type": "string",
            "description": "Label for the radio group"
          },
          "disabled": {
            "type": "boolean",
            "default": false,
            "description": "Disable all radio buttons"
          },
          "required": {
            "type": "boolean",
            "default": false,
            "description": "Mark the group as required"
          },
          "error": {
            "type": "string",
            "description": "Error message to display"
          },
          "orientation": {
            "type": "string",
            "default": "vertical",
            "description": "Layout orientation (vertical or horizontal)"
          },
          "ariaLabel": {
            "type": "string",
            "description": "Accessible label for the radiogroup"
          },
          "ariaLabelledBy": {
            "type": "string",
            "description": "ID of the element that labels the radiogroup"
          },
          "ariaDescribedBy": {
            "type": "string",
            "description": "ID(s) of element(s) that describe the radiogroup (hint or error text). Auto-set by FieldLabel."
          },
          "invalid": {
            "type": "boolean",
            "description": "Marks the group as invalid (sets aria-invalid)"
          },
          "className": {
            "type": "string",
            "description": "Additional CSS classes"
          }
        }
      },
      "storyDir": "radio-button"
    },
    "SelectButton": {
      "name": "SelectButton",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import cn from 'classnames';\nimport React, { useState } from 'react';\nimport { SelectButton } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\nimport { basicOptions } from './select-button-story-data';\n\nconst code = `import { SelectButton } from 'fluxo-ui';\n\nfunction MyComponent() {\n  const [value, setValue] = useState('option2');\n\n  const options = [\n    { label: 'Option 1', value: 'option1' },\n    { label: 'Option 2', value: 'option2' },\n    { label: 'Option 3', value: 'option3' },\n  ];\n\n  return (\n    <SelectButton\n      items={options}\n      value={value}\n      onChange={(e) => setValue(e.value)}\n    />\n  );\n}`;\n\nconst BasicUsage: React.FC = () => {\n    const { isDark } = useStoryTheme();\n    const [singleValue, setSingleValue] = useState('option2');\n\n    return (\n        <>\n            <ComponentDemo title=\"Single Selection\">\n                <SelectButton items={basicOptions} value={singleValue} onChange={(e) => setSingleValue(e.value)} />\n                <div className={cn('mt-4 text-sm', { 'text-gray-400': isDark, 'text-gray-600': !isDark })}>Selected: {singleValue}</div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock title=\"Basic Example\" code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "DisabledItems",
          "code": "import React from 'react';\nimport { SelectButton } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { disabledItemsOptions } from './select-button-story-data';\n\nconst code = `const options = [\n  { label: 'Available', value: 'available' },\n  { label: 'Disabled', value: 'disabled', disabled: true },\n  { label: 'Also Available', value: 'available2' },\n];\n\n<SelectButton\n  items={options}\n  value={value}\n  onChange={(e) => setValue(e.value)}\n/>`;\n\nconst DisabledItems: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo title=\"Specific Items Disabled\">\n                <SelectButton items={disabledItemsOptions} value=\"available\" onChange={(e) => console.log('Selected:', e.value)} />\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default DisabledItems;\n"
        },
        {
          "title": "DisabledState",
          "code": "import React from 'react';\nimport { SelectButton } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { basicOptions } from './select-button-story-data';\n\nconst code = `<SelectButton\n  items={options}\n  value={value}\n  onChange={(e) => setValue(e.value)}\n  disabled\n/>`;\n\nconst DisabledState: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo title=\"Fully Disabled\">\n                <SelectButton items={basicOptions} value=\"option2\" disabled />\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default DisabledState;\n"
        },
        {
          "title": "MultipleSelection",
          "code": "import cn from 'classnames';\nimport React, { useState } from 'react';\nimport { SelectButton } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\nimport { multipleOptions } from './select-button-story-data';\n\nconst code = `const [value, setValue] = useState<string[]>(['option2', 'option3']);\n\nconst options = [\n  { label: 'Option 1', value: 'option1' },\n  { label: 'Option 2', value: 'option2' },\n  { label: 'Option 3', value: 'option3' },\n  { label: 'Option 4', value: 'option4' },\n];\n\n<SelectButton\n  items={options}\n  value={value}\n  onChange={(e) => setValue(e.value)}\n  multiple\n/>`;\n\nconst MultipleSelection: React.FC = () => {\n    const { isDark } = useStoryTheme();\n    const [multipleValue, setMultipleValue] = useState<string[]>(['option2', 'option3']);\n\n    return (\n        <>\n            <ComponentDemo title=\"Multiple Selection Mode\">\n                <SelectButton items={multipleOptions} value={multipleValue} onChange={(e) => setMultipleValue(e.value)} multiple />\n                <div className={cn('mt-4 text-sm', { 'text-gray-400': isDark, 'text-gray-600': !isDark })}>\n                    Selected: {multipleValue.join(', ')}\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default MultipleSelection;\n"
        },
        {
          "title": "RealWorldExamples",
          "code": "import React from 'react';\nimport { SelectButton } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst GridIcon = (props: React.SVGProps<SVGSVGElement>) => (\n    <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" strokeWidth={1.5} stroke=\"currentColor\" {...props}>\n        <path\n            strokeLinecap=\"round\"\n            strokeLinejoin=\"round\"\n            d=\"M3.75 6A2.25 2.25 0 0 1 6 3.75h2.25A2.25 2.25 0 0 1 10.5 6v2.25a2.25 2.25 0 0 1-2.25 2.25H6a2.25 2.25 0 0 1-2.25-2.25V6ZM3.75 15.75A2.25 2.25 0 0 1 6 13.5h2.25a2.25 2.25 0 0 1 2.25 2.25V18a2.25 2.25 0 0 1-2.25 2.25H6A2.25 2.25 0 0 1 3.75 18v-2.25ZM13.5 6a2.25 2.25 0 0 1 2.25-2.25H18A2.25 2.25 0 0 1 20.25 6v2.25A2.25 2.25 0 0 1 18 10.5h-2.25a2.25 2.25 0 0 1-2.25-2.25V6ZM13.5 15.75a2.25 2.25 0 0 1 2.25-2.25H18a2.25 2.25 0 0 1 2.25 2.25V18A2.25 2.25 0 0 1 18 20.25h-2.25A2.25 2.25 0 0 1 13.5 18v-2.25Z\"\n        />\n    </svg>\n);\n\nconst ListIcon = (props: React.SVGProps<SVGSVGElement>) => (\n    <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" strokeWidth={1.5} stroke=\"currentColor\" {...props}>\n        <path\n            strokeLinecap=\"round\"\n            strokeLinejoin=\"round\"\n            d=\"M8.25 6.75h12M8.25 12h12m-12 5.25h12M3.75 6.75h.007v.008H3.75V6.75Zm.375 0a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0ZM3.75 12h.007v.008H3.75V12Zm.375 0a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Zm-.375 5.25h.007v.008H3.75v-.008Zm.375 0a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Z\"\n        />\n    </svg>\n);\n\nconst AlignLeftIcon = (props: React.SVGProps<SVGSVGElement>) => (\n    <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" strokeWidth={1.5} stroke=\"currentColor\" {...props}>\n        <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25H12\" />\n    </svg>\n);\n\nconst AlignCenterIcon = (props: React.SVGProps<SVGSVGElement>) => (\n    <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" strokeWidth={1.5} stroke=\"currentColor\" {...props}>\n        <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5\" />\n    </svg>\n);\n\nconst AlignRightIcon = (props: React.SVGProps<SVGSVGElement>) => (\n    <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" strokeWidth={1.5} stroke=\"currentColor\" {...props}>\n        <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M3.75 6.75h16.5M3.75 12h16.5M12 17.25h8.25\" />\n    </svg>\n);\n\nconst viewSwitcherItems = [\n    { label: 'Grid', value: 'grid', icon: GridIcon },\n    { label: 'List', value: 'list', icon: ListIcon },\n];\n\nconst alignmentItems = [\n    { label: 'Left', value: 'left', icon: AlignLeftIcon },\n    { label: 'Center', value: 'center', icon: AlignCenterIcon },\n    { label: 'Right', value: 'right', icon: AlignRightIcon },\n];\n\nconst code = `// View Switcher\n<SelectButton\n  items={[\n    { label: 'Grid', value: 'grid', icon: GridIcon },\n    { label: 'List', value: 'list', icon: ListIcon },\n  ]}\n  value={viewMode}\n  onChange={(e) => setViewMode(e.value)}\n/>\n\n// Text Alignment\n<SelectButton\n  items={[\n    { label: 'Left', value: 'left', icon: AlignLeftIcon },\n    { label: 'Center', value: 'center', icon: AlignCenterIcon },\n    { label: 'Right', value: 'right', icon: AlignRightIcon },\n  ]}\n  value={alignment}\n  onChange={(e) => setAlignment(e.value)}\n/>`;\n\nconst RealWorldExamples: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo title=\"View Switcher\">\n                <SelectButton items={viewSwitcherItems} value=\"grid\" />\n            </ComponentDemo>\n\n            <ComponentDemo title=\"Text Alignment\">\n                <SelectButton items={alignmentItems} value=\"left\" />\n            </ComponentDemo>\n\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default RealWorldExamples;\n"
        },
        {
          "title": "SizeVariants",
          "code": "import cn from 'classnames';\nimport React from 'react';\nimport { SelectButton } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\nimport { basicOptions } from './select-button-story-data';\n\nconst code = `<SelectButton items={options} value={value} size=\"sm\" />\n<SelectButton items={options} value={value} size=\"md\" />\n<SelectButton items={options} value={value} size=\"lg\" />`;\n\nconst SizeVariants: React.FC = () => {\n    const { isDark } = useStoryTheme();\n\n    return (\n        <>\n            <ComponentDemo title=\"Different Sizes\">\n                <div className=\"space-y-4\">\n                    <div>\n                        <div className={cn('text-sm mb-2', { 'text-gray-400': isDark, 'text-gray-600': !isDark })}>Small</div>\n                        <SelectButton items={basicOptions} value=\"option2\" size=\"sm\" />\n                    </div>\n                    <div>\n                        <div className={cn('text-sm mb-2', { 'text-gray-400': isDark, 'text-gray-600': !isDark })}>\n                            Medium (default)\n                        </div>\n                        <SelectButton items={basicOptions} value=\"option2\" size=\"md\" />\n                    </div>\n                    <div>\n                        <div className={cn('text-sm mb-2', { 'text-gray-400': isDark, 'text-gray-600': !isDark })}>Large</div>\n                        <SelectButton items={basicOptions} value=\"option2\" size=\"lg\" />\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default SizeVariants;\n"
        },
        {
          "title": "ThemeVariants",
          "code": "import cn from 'classnames';\nimport React from 'react';\nimport { SelectButton } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\nimport { basicOptions } from './select-button-story-data';\n\nconst code = `<SelectButton items={options} value={value} theme=\"primary\" />\n<SelectButton items={options} value={value} theme=\"success\" />\n<SelectButton items={options} value={value} theme=\"secondary\" />`;\n\nconst ThemeVariants: React.FC = () => {\n    const { isDark } = useStoryTheme();\n\n    return (\n        <>\n            <ComponentDemo title=\"Different Themes\">\n                <div className=\"space-y-4\">\n                    <div>\n                        <div className={cn('text-sm mb-2', { 'text-gray-400': isDark, 'text-gray-600': !isDark })}>Primary</div>\n                        <SelectButton items={basicOptions} value=\"option2\" theme=\"primary\" />\n                    </div>\n                    <div>\n                        <div className={cn('text-sm mb-2', { 'text-gray-400': isDark, 'text-gray-600': !isDark })}>Success</div>\n                        <SelectButton items={basicOptions} value=\"option2\" theme=\"success\" />\n                    </div>\n                    <div>\n                        <div className={cn('text-sm mb-2', { 'text-gray-400': isDark, 'text-gray-600': !isDark })}>Secondary</div>\n                        <SelectButton items={basicOptions} value=\"option2\" theme=\"secondary\" />\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default ThemeVariants;\n"
        },
        {
          "title": "UsageNotes",
          "code": "import cn from 'classnames';\nimport React from 'react';\nimport { useStoryTheme } from '../../StoryThemeContext';\n\nconst UsageNotes: React.FC = () => {\n    const { isDark } = useStoryTheme();\n\n    return (\n        <div\n            className={cn('rounded-lg p-6 space-y-4', {\n                'bg-gray-800 text-gray-300': isDark,\n                'bg-gray-100 text-gray-700': !isDark,\n            })}\n        >\n            <div>\n                <h3 className={cn('font-semibold mb-2', { 'text-gray-100': isDark, 'text-gray-900': !isDark })}>\n                    ListItem Structure\n                </h3>\n                <p className=\"text-sm\">\n                    Each item in the{' '}\n                    <code\n                        className={cn('px-2 py-1 rounded', {\n                            'text-primary-400 bg-gray-900': isDark,\n                            'text-primary-700 bg-gray-200': !isDark,\n                        })}\n                    >\n                        items\n                    </code>{' '}\n                    array should have:\n                </p>\n                <ul className=\"list-disc list-inside ml-4 mt-2 text-sm space-y-1\">\n                    <li>\n                        <code className=\"text-primary-400\">value</code>: The value to use when selected\n                    </li>\n                    <li>\n                        <code className=\"text-primary-400\">label</code>: The display text\n                    </li>\n                    <li>\n                        <code className=\"text-primary-400\">disabled</code>: (optional) Disable this specific item\n                    </li>\n                    <li>\n                        <code className=\"text-primary-400\">icon</code>: (optional) Icon component or element to display\n                    </li>\n                </ul>\n            </div>\n            <div>\n                <h3 className={cn('font-semibold mb-2', { 'text-gray-100': isDark, 'text-gray-900': !isDark })}>\n                    Multiple Selection\n                </h3>\n                <p className=\"text-sm\">\n                    When{' '}\n                    <code\n                        className={cn('px-2 py-1 rounded', {\n                            'text-primary-400 bg-gray-900': isDark,\n                            'text-primary-700 bg-gray-200': !isDark,\n                        })}\n                    >\n                        multiple={'{true}'}\n                    </code>\n                    , the value prop should be an array of selected values. Users can select/deselect multiple items.\n                </p>\n            </div>\n            <div>\n                <h3 className={cn('font-semibold mb-2', { 'text-gray-100': isDark, 'text-gray-900': !isDark })}>Hidden Input</h3>\n                <p className=\"text-sm\">\n                    SelectButton includes a hidden input field for form submissions. The{' '}\n                    <code\n                        className={cn('px-2 py-1 rounded', {\n                            'text-primary-400 bg-gray-900': isDark,\n                            'text-primary-700 bg-gray-200': !isDark,\n                        })}\n                    >\n                        name\n                    </code>{' '}\n                    prop sets the input's name attribute. For multiple selection, values are comma-separated.\n                </p>\n            </div>\n            <div>\n                <h3 className={cn('font-semibold mb-2', { 'text-gray-100': isDark, 'text-gray-900': !isDark })}>Accessibility</h3>\n                <p className=\"text-sm\">\n                    The component uses proper ARIA attributes (\n                    <code\n                        className={cn('px-2 py-1 rounded', {\n                            'text-primary-400 bg-gray-900': isDark,\n                            'text-primary-700 bg-gray-200': !isDark,\n                        })}\n                    >\n                        role=\"group\"\n                    </code>\n                    ,\n                    <code\n                        className={cn('px-2 py-1 rounded ml-1', {\n                            'text-primary-400 bg-gray-900': isDark,\n                            'text-primary-700 bg-gray-200': !isDark,\n                        })}\n                    >\n                        aria-pressed\n                    </code>\n                    ) for screen reader support.\n                </p>\n            </div>\n        </div>\n    );\n};\n\nexport default UsageNotes;\n"
        },
        {
          "title": "Variants",
          "code": "import React, { useState } from 'react';\nimport { SelectButton } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst items = [\n    { value: 'day', label: 'Day' },\n    { value: 'week', label: 'Week' },\n    { value: 'month', label: 'Month' },\n    { value: 'year', label: 'Year' },\n];\n\nconst code = `// Segmented (iOS-style pill)\n<SelectButton variant=\"segmented\" items={items} value={value} onChange={(e) => setValue(e.value)} />\n\n// Pill (rounded with gap)\n<SelectButton variant=\"pill\" items={items} value={value} onChange={(e) => setValue(e.value)} />\n\n// Underline (tabs-style)\n<SelectButton variant=\"underline\" items={items} value={value} onChange={(e) => setValue(e.value)} />`;\n\nconst Variants: React.FC = () => {\n    const [seg, setSeg] = useState('week');\n    const [pill, setPill] = useState('week');\n    const [und, setUnd] = useState('week');\n    const [full, setFull] = useState('week');\n\n    return (\n        <>\n            <ComponentDemo title=\"Segmented (default new variant)\" description=\"Pill-shaped segmented control — perfect for mobile range/scope toggles.\">\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16 }}>\n                    <SelectButton variant=\"segmented\" items={items} value={seg} onChange={(e) => setSeg(e.value as string)} />\n                    <div\n                        style={{\n                            padding: '10px 14px',\n                            background: 'var(--eui-bg-subtle)',\n                            border: '1px solid var(--eui-border-subtle)',\n                            borderRadius: 6,\n                            fontSize: 12,\n                            color: 'var(--eui-text-muted)',\n                        }}\n                    >\n                        Selected: <strong style={{ color: 'var(--eui-text)' }}>{seg}</strong>\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n\n            <ComponentDemo title=\"Pill variant\" description=\"Rounded chips with gaps — wraps onto multiple rows when space is tight.\" className=\"mt-4\">\n                <div style={{ width: '100%' }}>\n                    <SelectButton variant=\"pill\" items={items} value={pill} onChange={(e) => setPill(e.value as string)} />\n                </div>\n            </ComponentDemo>\n\n            <ComponentDemo title=\"Underline (tabs-style)\" description=\"Used as a horizontal section selector — minimal chrome, single accent line.\" className=\"mt-4\">\n                <div style={{ width: '100%' }}>\n                    <SelectButton variant=\"underline\" items={items} value={und} onChange={(e) => setUnd(e.value as string)} />\n                </div>\n            </ComponentDemo>\n\n            <ComponentDemo title=\"Full-width segmented\" description=\"Stretch the group to fill the available width — items split evenly.\" className=\"mt-4\">\n                <div style={{ width: '100%', maxWidth: 380 }}>\n                    <SelectButton fullWidth variant=\"segmented\" items={items} value={full} onChange={(e) => setFull(e.value as string)} />\n                </div>\n            </ComponentDemo>\n        </>\n    );\n};\n\nexport default Variants;\n"
        },
        {
          "title": "VerticalDirection",
          "code": "import React, { useState } from 'react';\nimport { SelectButton } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { sizeOptions } from './select-button-story-data';\n\nconst code = `<SelectButton\n  items={options}\n  value={value}\n  onChange={(e) => setValue(e.value)}\n  direction=\"vertical\"\n/>`;\n\nconst VerticalDirection: React.FC = () => {\n    const [verticalValue, setVerticalValue] = useState('medium');\n\n    return (\n        <>\n            <ComponentDemo title=\"Vertical Layout\">\n                <SelectButton\n                    items={sizeOptions}\n                    value={verticalValue}\n                    onChange={(e) => setVerticalValue(e.value)}\n                    direction=\"vertical\"\n                />\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default VerticalDirection;\n"
        },
        {
          "title": "WithIcons",
          "code": "import React, { useState } from 'react';\nimport { SelectButton } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { iconOptions } from './select-button-story-data';\n\nconst code = `const HeartIcon = (props) => (\n  <svg {...props}>\n    {/* icon path */}\n  </svg>\n);\n\nconst options = [\n  { label: 'Heart', value: 'heart', icon: HeartIcon },\n  { label: 'Star', value: 'star', icon: StarIcon },\n  { label: 'Fire', value: 'fire', icon: FireIcon },\n];\n\n<SelectButton\n  items={options}\n  value={value}\n  onChange={(e) => setValue(e.value)}\n/>`;\n\nconst WithIcons: React.FC = () => {\n    const [iconValue, setIconValue] = useState('heart');\n\n    return (\n        <>\n            <ComponentDemo title=\"Buttons with Icons\">\n                <SelectButton items={iconOptions} value={iconValue} onChange={(e) => setIconValue(e.value)} />\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default WithIcons;\n"
        },
        {
          "title": "select-button-story-data",
          "code": "import React from 'react';\n\nexport const basicOptions = [\n    { label: 'Option 1', value: 'option1' },\n    { label: 'Option 2', value: 'option2' },\n    { label: 'Option 3', value: 'option3' },\n];\n\nexport const multipleOptions = [\n    { label: 'Option 1', value: 'option1' },\n    { label: 'Option 2', value: 'option2' },\n    { label: 'Option 3', value: 'option3' },\n    { label: 'Option 4', value: 'option4' },\n];\n\nexport const sizeOptions = [\n    { label: 'Small', value: 'small' },\n    { label: 'Medium', value: 'medium' },\n    { label: 'Large', value: 'large' },\n];\n\nexport const disabledItemsOptions = [\n    { label: 'Available', value: 'available' },\n    { label: 'Disabled', value: 'disabled', disabled: true },\n    { label: 'Also Available', value: 'available2' },\n];\n\nexport const HeartIcon = (props: React.SVGProps<SVGSVGElement>) => (\n    <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" strokeWidth={1.5} stroke=\"currentColor\" {...props}>\n        <path\n            strokeLinecap=\"round\"\n            strokeLinejoin=\"round\"\n            d=\"M21 8.25c0-2.485-2.099-4.5-4.688-4.5-1.935 0-3.597 1.126-4.312 2.733-.715-1.607-2.377-2.733-4.313-2.733C5.1 3.75 3 5.765 3 8.25c0 7.22 9 12 9 12s9-4.78 9-12Z\"\n        />\n    </svg>\n);\n\nexport const StarIcon = (props: React.SVGProps<SVGSVGElement>) => (\n    <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" strokeWidth={1.5} stroke=\"currentColor\" {...props}>\n        <path\n            strokeLinecap=\"round\"\n            strokeLinejoin=\"round\"\n            d=\"M11.48 3.499a.562.562 0 0 1 1.04 0l2.125 5.111a.563.563 0 0 0 .475.345l5.518.442c.499.04.701.663.321.988l-4.204 3.602a.563.563 0 0 0-.182.557l1.285 5.385a.562.562 0 0 1-.84.61l-4.725-2.885a.562.562 0 0 0-.586 0L6.982 20.54a.562.562 0 0 1-.84-.61l1.285-5.386a.562.562 0 0 0-.182-.557l-4.204-3.602a.562.562 0 0 1 .321-.988l5.518-.442a.563.563 0 0 0 .475-.345L11.48 3.5Z\"\n        />\n    </svg>\n);\n\nexport const FireIcon = (props: React.SVGProps<SVGSVGElement>) => (\n    <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" strokeWidth={1.5} stroke=\"currentColor\" {...props}>\n        <path\n            strokeLinecap=\"round\"\n            strokeLinejoin=\"round\"\n            d=\"M15.362 5.214A8.252 8.252 0 0 1 12 21 8.25 8.25 0 0 1 6.038 7.047 8.287 8.287 0 0 0 9 9.601a8.983 8.983 0 0 1 3.361-6.867 8.21 8.21 0 0 0 3 2.48Z\"\n        />\n        <path\n            strokeLinecap=\"round\"\n            strokeLinejoin=\"round\"\n            d=\"M12 18a3.75 3.75 0 0 0 .495-7.468 5.99 5.99 0 0 0-1.925 3.547 5.975 5.975 0 0 1-2.133-1.001A3.75 3.75 0 0 0 12 18Z\"\n        />\n    </svg>\n);\n\nexport const iconOptions = [\n    { label: 'Heart', value: 'heart', icon: HeartIcon },\n    { label: 'Star', value: 'star', icon: StarIcon },\n    { label: 'Fire', value: 'fire', icon: FireIcon },\n];\n"
        }
      ],
      "props": {
        "selectButtonProps": {
          "items": {
            "type": "ListItem[]",
            "required": true,
            "description": "Array of items to display. Each item has { value: any, label: any, disabled?: boolean, icon?: IconComponent | ReactElement }"
          },
          "value": {
            "type": "T | T[]",
            "description": "Selected value(s). Single value for single selection, array of values for multiple selection"
          },
          "onChange": {
            "type": "(event: ComponentEvent<T>) => void",
            "description": "Callback fired when selection changes. Receives ComponentEvent with the new value"
          },
          "multiple": {
            "type": "boolean",
            "default": "false",
            "description": "Enable multiple selection mode. When true, value should be an array"
          },
          "required": {
            "type": "boolean",
            "default": "false",
            "description": "Mark the field as required (affects hidden input)"
          },
          "direction": {
            "type": "'horizontal' | 'vertical'",
            "default": "'horizontal'",
            "description": "Layout direction of the button group"
          },
          "variant": {
            "type": "'default' | 'segmented' | 'pill' | 'underline'",
            "default": "'default'",
            "description": "Visual style. 'segmented' renders an iOS-style pill segmented control (great for mobile). 'pill' renders rounded pill chips with gaps. 'underline' renders a tab-like underlined row."
          },
          "fullWidth": {
            "type": "boolean",
            "default": "false",
            "description": "Stretch the group to fill its container width with items distributed evenly. Useful inside mobile toolbars."
          },
          "disabled": {
            "type": "boolean",
            "default": "false",
            "description": "Disable all buttons in the group"
          },
          "className": {
            "type": "string",
            "description": "Additional CSS classes for the container"
          },
          "name": {
            "type": "string",
            "description": "Name attribute for the hidden input field (useful for form submissions)"
          },
          "size": {
            "type": "'sm' | 'md' | 'lg' | 'xl'",
            "description": "Size variant (inherited from BaseComponentProps)"
          },
          "theme": {
            "type": "'default' | 'primary' | 'secondary' | 'success' | 'dark'",
            "description": "Theme variant (inherited from BaseComponentProps)"
          },
          "borderRadius": {
            "type": "string",
            "description": "Custom border radius (inherited from BaseComponentProps)"
          },
          "borderColor": {
            "type": "string",
            "description": "Custom border color (inherited from BaseComponentProps)"
          },
          "borderWidth": {
            "type": "string",
            "description": "Custom border width (inherited from BaseComponentProps)"
          },
          "backgroundColor": {
            "type": "string",
            "description": "Custom background color (inherited from BaseComponentProps)"
          },
          "fontSize": {
            "type": "string",
            "description": "Custom font size (inherited from BaseComponentProps)"
          },
          "fontColor": {
            "type": "string",
            "description": "Custom font color (inherited from BaseComponentProps)"
          }
        }
      },
      "storyDir": "select-button"
    },
    "Stepper": {
      "name": "Stepper",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import cn from 'classnames';\nimport React, { useState } from 'react';\nimport { Stepper } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\nimport { detailedSteps } from './stepper-story-data';\n\nconst code = `import { Stepper } from 'fluxo-ui';\n\nconst steps = [\n  { label: 'Account Setup', description: 'Create your account credentials' },\n  { label: 'Personal Info', description: 'Fill in your personal details' },\n  { label: 'Preferences', description: 'Customize your experience', optional: true },\n  { label: 'Confirmation', description: 'Review and confirm' },\n];\n\n<Stepper steps={steps} activeStep={1} />`;\n\nconst BasicUsage: React.FC = () => {\n    const { isDark } = useStoryTheme();\n    const [active, setActive] = useState(1);\n\n    return (\n        <>\n            <ComponentDemo title=\"Basic Stepper\" description=\"Simple numbered stepper with descriptions\" centered={false}>\n                <div className=\"w-full p-4\">\n                    <Stepper steps={detailedSteps} activeStep={active} />\n                    <div className=\"flex gap-3 mt-6 justify-center\">\n                        <button\n                            className={cn('px-3 py-1.5 text-sm rounded-md', {\n                                'bg-gray-700 text-gray-200': isDark,\n                                'bg-gray-200 text-gray-700': !isDark,\n                            })}\n                            onClick={() => setActive(Math.max(0, active - 1))}\n                        >\n                            Back\n                        </button>\n                        <button\n                            className=\"px-3 py-1.5 text-sm rounded-md bg-blue-500 text-white\"\n                            onClick={() => setActive(Math.min(detailedSteps.length - 1, active + 1))}\n                        >\n                            Next\n                        </button>\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "ColorVariants",
          "code": "import cn from 'classnames';\nimport React from 'react';\nimport { Stepper } from '../../../components';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\nimport { basicSteps } from './stepper-story-data';\n\nconst variants = ['primary', 'success', 'warning', 'danger', 'info', 'default'] as const;\n\nconst ColorVariants: React.FC = () => {\n    const { isDark } = useStoryTheme();\n\n    return (\n        <ComponentDemo title=\"Color Variants\" description=\"Different color themes for the stepper\" centered={false}>\n            <div className=\"w-full space-y-6 p-4\">\n                {variants.map((v) => (\n                    <div key={v}>\n                        <p className={cn('text-sm mb-2 font-medium capitalize', { 'text-gray-400': isDark, 'text-gray-600': !isDark })}>{v}</p>\n                        <Stepper steps={basicSteps} activeStep={2} variant={v} layout=\"rounded\" />\n                    </div>\n                ))}\n            </div>\n        </ComponentDemo>\n    );\n};\n\nexport default ColorVariants;\n"
        },
        {
          "title": "InteractiveSteps",
          "code": "import cn from 'classnames';\nimport React, { useState } from 'react';\nimport { Stepper } from '../../../components';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\nimport { detailedSteps } from './stepper-story-data';\n\nconst InteractiveSteps: React.FC = () => {\n    const { isDark } = useStoryTheme();\n    const [activeFree, setActiveFree] = useState(0);\n    const [activeLinear, setActiveLinear] = useState(1);\n\n    return (\n        <ComponentDemo title=\"Clickable Steps\" description=\"Click on steps to navigate\" centered={false}>\n            <div className=\"w-full space-y-8 p-4\">\n                <div>\n                    <p className={cn('text-sm mb-2 font-medium', { 'text-gray-400': isDark, 'text-gray-600': !isDark })}>Free navigation</p>\n                    <Stepper steps={detailedSteps} activeStep={activeFree} clickable onChange={setActiveFree} layout=\"rounded\" />\n                </div>\n                <div>\n                    <p className={cn('text-sm mb-2 font-medium', { 'text-gray-400': isDark, 'text-gray-600': !isDark })}>Linear (next step only)</p>\n                    <Stepper steps={detailedSteps} activeStep={activeLinear} clickable linear onChange={setActiveLinear} layout=\"rounded\" />\n                    <button className={cn('mt-3 px-3 py-1.5 text-xs rounded-md', { 'bg-gray-700 text-gray-300': isDark, 'bg-gray-200 text-gray-600': !isDark })} onClick={() => setActiveLinear(0)}>Reset</button>\n                </div>\n            </div>\n        </ComponentDemo>\n    );\n};\n\nexport default InteractiveSteps;\n"
        },
        {
          "title": "LabelPlacement",
          "code": "import cn from 'classnames';\nimport React from 'react';\nimport { Stepper } from '../../../components';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\nimport { basicSteps } from './stepper-story-data';\n\nconst placements = [\n    { key: 'bottom', label: 'Bottom (default)' },\n    { key: 'right', label: 'Right' },\n    { key: 'alternate', label: 'Alternate' },\n] as const;\n\nconst LabelPlacement: React.FC = () => {\n    const { isDark } = useStoryTheme();\n\n    return (\n        <ComponentDemo title=\"Label Positions\" description=\"Labels positioned below, to the right, or alternating\" centered={false}>\n            <div className=\"w-full space-y-8 p-4\">\n                {placements.map(({ key, label }) => (\n                    <div key={key}>\n                        <p className={cn('text-sm mb-2 font-medium', { 'text-gray-400': isDark, 'text-gray-600': !isDark })}>{label}</p>\n                        <Stepper steps={basicSteps} activeStep={1} labelPlacement={key} layout=\"rounded\" />\n                    </div>\n                ))}\n            </div>\n        </ComponentDemo>\n    );\n};\n\nexport default LabelPlacement;\n"
        },
        {
          "title": "LayoutShapes",
          "code": "import cn from 'classnames';\nimport React from 'react';\nimport { Stepper } from '../../../components';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\nimport { basicSteps } from './stepper-story-data';\n\nconst layouts = [\n    { key: 'default', label: 'Default (Rounded Rect)' },\n    { key: 'rounded', label: 'Rounded (Circle)' },\n    { key: 'square', label: 'Square' },\n    { key: 'rectangle', label: 'Rectangle (Pill)' },\n    { key: 'dot', label: 'Dot' },\n    { key: 'minimal', label: 'Minimal' },\n] as const;\n\nconst LayoutShapes: React.FC = () => {\n    const { isDark } = useStoryTheme();\n\n    return (\n        <ComponentDemo title=\"Indicator Shapes\" description=\"Different shapes for step indicators\" centered={false}>\n            <div className=\"w-full space-y-8 p-4\">\n                {layouts.map(({ key, label }) => (\n                    <div key={key}>\n                        <p className={cn('text-sm mb-2 font-medium', { 'text-gray-400': isDark, 'text-gray-600': !isDark })}>{label}</p>\n                        <Stepper steps={basicSteps} activeStep={1} layout={key} />\n                    </div>\n                ))}\n            </div>\n        </ComponentDemo>\n    );\n};\n\nexport default LayoutShapes;\n"
        },
        {
          "title": "SizeOptions",
          "code": "import cn from 'classnames';\nimport React from 'react';\nimport { Stepper } from '../../../components';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\nimport { basicSteps } from './stepper-story-data';\n\nconst sizes = ['xs', 'sm', 'md', 'lg', 'xl'] as const;\n\nconst SizeOptions: React.FC = () => {\n    const { isDark } = useStoryTheme();\n\n    return (\n        <ComponentDemo title=\"Size Options\" description=\"Five sizes from xs to xl\" centered={false}>\n            <div className=\"w-full space-y-8 p-4\">\n                {sizes.map((s) => (\n                    <div key={s}>\n                        <p className={cn('text-sm mb-2 font-medium', { 'text-gray-400': isDark, 'text-gray-600': !isDark })}>{s.toUpperCase()}</p>\n                        <Stepper steps={basicSteps} activeStep={1} size={s} layout=\"rounded\" />\n                    </div>\n                ))}\n            </div>\n        </ComponentDemo>\n    );\n};\n\nexport default SizeOptions;\n"
        },
        {
          "title": "StepStatus",
          "code": "import cn from 'classnames';\nimport React from 'react';\nimport { Stepper } from '../../../components';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\nimport { statusSteps, warningSteps } from './stepper-story-data';\n\nconst StepStatus: React.FC = () => {\n    const { isDark } = useStoryTheme();\n\n    return (\n        <ComponentDemo title=\"Error & Warning States\" description=\"Individual steps can have error or warning status\" centered={false}>\n            <div className=\"w-full space-y-8 p-4\">\n                <div>\n                    <p className={cn('text-sm mb-2 font-medium', { 'text-gray-400': isDark, 'text-gray-600': !isDark })}>With Error Step</p>\n                    <Stepper steps={statusSteps} activeStep={1} layout=\"rounded\" />\n                </div>\n                <div>\n                    <p className={cn('text-sm mb-2 font-medium', { 'text-gray-400': isDark, 'text-gray-600': !isDark })}>With Warning Step</p>\n                    <Stepper steps={warningSteps} activeStep={2} layout=\"rounded\" />\n                </div>\n            </div>\n        </ComponentDemo>\n    );\n};\n\nexport default StepStatus;\n"
        },
        {
          "title": "TextOnly",
          "code": "import cn from 'classnames';\nimport React from 'react';\nimport { Stepper } from '../../../components';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\nimport { detailedSteps } from './stepper-story-data';\n\nconst TextOnly: React.FC = () => {\n    const { isDark } = useStoryTheme();\n\n    return (\n        <ComponentDemo title=\"Minimal & Dot Styles\" description=\"Steps without numbers or icons, text labels only\" centered={false}>\n            <div className=\"w-full space-y-8 p-4\">\n                <div>\n                    <p className={cn('text-sm mb-2 font-medium', { 'text-gray-400': isDark, 'text-gray-600': !isDark })}>Minimal (no background)</p>\n                    <Stepper steps={detailedSteps} activeStep={2} layout=\"minimal\" showStepNumbers={false} />\n                </div>\n                <div>\n                    <p className={cn('text-sm mb-2 font-medium', { 'text-gray-400': isDark, 'text-gray-600': !isDark })}>Dot indicators</p>\n                    <Stepper steps={detailedSteps} activeStep={2} layout=\"dot\" showStepNumbers={false} />\n                </div>\n            </div>\n        </ComponentDemo>\n    );\n};\n\nexport default TextOnly;\n"
        },
        {
          "title": "VerticalOrientation",
          "code": "import cn from 'classnames';\nimport React from 'react';\nimport { Stepper } from '../../../components';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\nimport { detailedSteps, iconSteps } from './stepper-story-data';\n\nconst VerticalOrientation: React.FC = () => {\n    const { isDark } = useStoryTheme();\n\n    return (\n        <ComponentDemo title=\"Vertical Orientation\" description=\"Stepper in vertical layout\">\n            <div className=\"flex gap-12 flex-wrap\">\n                <div>\n                    <p className={cn('text-sm mb-3 font-medium', { 'text-gray-400': isDark, 'text-gray-600': !isDark })}>Rounded</p>\n                    <Stepper steps={detailedSteps} activeStep={1} orientation=\"vertical\" layout=\"rounded\" />\n                </div>\n                <div>\n                    <p className={cn('text-sm mb-3 font-medium', { 'text-gray-400': isDark, 'text-gray-600': !isDark })}>With Icons</p>\n                    <Stepper steps={iconSteps.slice(0, 4)} activeStep={2} orientation=\"vertical\" layout=\"rounded\" showStepNumbers={false} />\n                </div>\n                <div>\n                    <p className={cn('text-sm mb-3 font-medium', { 'text-gray-400': isDark, 'text-gray-600': !isDark })}>Dot</p>\n                    <Stepper steps={detailedSteps} activeStep={2} orientation=\"vertical\" layout=\"dot\" showStepNumbers={false} />\n                </div>\n            </div>\n        </ComponentDemo>\n    );\n};\n\nexport default VerticalOrientation;\n"
        },
        {
          "title": "WithIcons",
          "code": "import cn from 'classnames';\nimport React from 'react';\nimport { Stepper } from '../../../components';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\nimport { iconSteps } from './stepper-story-data';\n\nconst WithIcons: React.FC = () => {\n    const { isDark } = useStoryTheme();\n\n    return (\n        <ComponentDemo title=\"Icon Steps\" description=\"Steps with custom icons for each step\" centered={false}>\n            <div className=\"w-full space-y-8 p-4\">\n                <div>\n                    <p className={cn('text-sm mb-2 font-medium', { 'text-gray-400': isDark, 'text-gray-600': !isDark })}>Rounded with Icons</p>\n                    <Stepper steps={iconSteps} activeStep={2} layout=\"rounded\" showStepNumbers={false} />\n                </div>\n                <div>\n                    <p className={cn('text-sm mb-2 font-medium', { 'text-gray-400': isDark, 'text-gray-600': !isDark })}>Square with Icons</p>\n                    <Stepper steps={iconSteps} activeStep={2} layout=\"square\" showStepNumbers={false} />\n                </div>\n                <div>\n                    <p className={cn('text-sm mb-2 font-medium', { 'text-gray-400': isDark, 'text-gray-600': !isDark })}>Rectangle with Icons</p>\n                    <Stepper steps={iconSteps} activeStep={2} layout=\"rectangle\" showStepNumbers={false} />\n                </div>\n            </div>\n        </ComponentDemo>\n    );\n};\n\nexport default WithIcons;\n"
        }
      ],
      "props": {
        "stepperProps": {
          "steps": {
            "type": "StepItem[]",
            "description": "Array of step definitions with label, description, icon, and status",
            "default": "-"
          },
          "activeStep": {
            "type": "number",
            "default": "0",
            "description": "Index of the currently active step"
          },
          "variant": {
            "type": "'default' | 'primary' | 'success' | 'warning' | 'danger' | 'info'",
            "default": "'primary'",
            "description": "Color variant"
          },
          "size": {
            "type": "'xs' | 'sm' | 'md' | 'lg' | 'xl'",
            "default": "'md'",
            "description": "Size of indicators and text"
          },
          "layout": {
            "type": "'default' | 'rounded' | 'square' | 'rectangle' | 'dot' | 'minimal'",
            "default": "'default'",
            "description": "Shape of step indicators"
          },
          "orientation": {
            "type": "'horizontal' | 'vertical'",
            "default": "'horizontal'",
            "description": "Layout direction"
          },
          "labelPlacement": {
            "type": "'bottom' | 'right' | 'alternate'",
            "default": "'bottom'",
            "description": "Position of labels relative to indicators"
          },
          "showStepNumbers": {
            "type": "boolean",
            "default": "true",
            "description": "Show step numbers inside indicators"
          },
          "showConnectors": {
            "type": "boolean",
            "default": "true",
            "description": "Show connector lines between steps"
          },
          "clickable": {
            "type": "boolean",
            "default": "false",
            "description": "Allow clicking on steps to navigate"
          },
          "linear": {
            "type": "boolean",
            "default": "false",
            "description": "Only allow clicking the next step"
          },
          "completedIcon": {
            "type": "ReactElement | IconComponent",
            "description": "Custom icon for completed steps"
          },
          "errorIcon": {
            "type": "ReactElement | IconComponent",
            "description": "Custom icon for error steps"
          },
          "onChange": {
            "type": "(step: number) => void",
            "description": "Callback when a step is clicked"
          },
          "connector": {
            "type": "ReactNode",
            "description": "Custom connector element"
          },
          "className": {
            "type": "string",
            "description": "Additional CSS class"
          },
          "disabled": {
            "type": "boolean",
            "default": "false",
            "description": "Disable all interaction"
          },
          "id": {
            "type": "string",
            "description": "HTML id attribute"
          },
          "ariaLabel": {
            "type": "string",
            "description": "Accessible label"
          },
          "autoCollapse": {
            "type": "boolean",
            "default": "true",
            "description": "When the horizontal stepper is wider than the space available, switch to the layout chosen by `collapseMode`. Turn off to always keep the full layout."
          },
          "collapseMode": {
            "type": "'scroll' | 'compact'",
            "default": "'scroll'",
            "description": "How the horizontal stepper behaves when it doesn't fit. 'scroll' lets the strip scroll horizontally so labels stay readable. 'compact' shrinks every step to an equal share of the width, hides the connectors, and truncates labels with an ellipsis so the whole progression is visible at once — best on phones and narrow panels."
          }
        }
      },
      "storyDir": "stepper"
    },
    "TextInput": {
      "name": "TextInput",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React, { useState } from 'react';\nimport { TextInput as TextInputRaw } from '../../../components';\nimport { withFieldLabel } from '../../../utils/field-label';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst TextInput = withFieldLabel(TextInputRaw);\n\nconst code = `import { TextInput } from 'fluxo-ui';\n\nfunction MyComponent() {\n  const [value, setValue] = useState('');\n\n  return (\n    <TextInput\n      placeholder=\"Enter some text...\"\n      value={value}\n      onChange={(e) => setValue(e.target.value)}\n    />\n  );\n}`;\n\nconst BasicUsage: React.FC = () => {\n    const [basicValue, setBasicValue] = useState('');\n\n    return (\n        <>\n            <ComponentDemo title=\"Basic Text Input\">\n                <div className=\"w-full max-w-sm\">\n                    <TextInput placeholder=\"Enter some text...\" value={basicValue} onChange={(e) => setBasicValue(e.value)} />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock title=\"Basic Example\" code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "TextInputStates",
          "code": "import React from 'react';\nimport { TextInput as TextInputRaw } from '../../../components';\nimport { withFieldLabel } from '../../../utils/field-label';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst TextInput = withFieldLabel(TextInputRaw);\n\nconst code = `<TextInput label=\"Normal\" placeholder=\"Normal state\" value={value} onChange={(e) => setValue(e.value)} />\n<TextInput label=\"Disabled\" placeholder=\"Disabled state\" value={value} onChange={(e) => setValue(e.value)} disabled />\n<TextInput label=\"Read Only\" value=\"Read only value\" readonly onChange={(e) => setValue(e.value)} />\n<TextInput label=\"Required\" placeholder=\"Required field\" value={value} onChange={(e) => setValue(e.value)} required />`;\n\nconst TextInputStates: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo title=\"Input States\">\n                <div className=\"w-full max-w-sm space-y-4\">\n                    <TextInput label=\"Normal\" placeholder=\"Normal state\" />\n                    <TextInput label=\"Disabled\" placeholder=\"Disabled state\" disabled />\n                    <TextInput label=\"Read Only\" value=\"Read only value\" readonly />\n                    <TextInput label=\"Required\" placeholder=\"Required field\" required />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default TextInputStates;\n"
        },
        {
          "title": "Validation",
          "code": "import React, { useState } from 'react';\nimport { TextInput as TextInputRaw } from '../../../components';\nimport { withFieldLabel } from '../../../utils/field-label';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst TextInput = withFieldLabel(TextInputRaw);\n\nconst code = `const [value, setValue] = useState('');\nconst [error, setError] = useState('');\n\nconst handleChange = (e) => {\n  const newValue = e.target.value;\n  setValue(newValue);\n\n  if (newValue.length < 3 && newValue.length > 0) {\n    setError('Must be at least 3 characters');\n  } else {\n    setError('');\n  }\n};\n\n<TextInput\n  label=\"Username\"\n  placeholder=\"Enter username\"\n  value={value}\n  onChange={handleChange}\n  error={error}\n/>`;\n\nconst Validation: React.FC = () => {\n    const [validatedValue, setValidatedValue] = useState('');\n    const [errorMessage, setErrorMessage] = useState('');\n\n    const handleValidatedChange = (e: { value: string }) => {\n        const val = e.value;\n        setValidatedValue(val);\n\n        if (val.length < 3 && val.length > 0) {\n            setErrorMessage('Must be at least 3 characters');\n        } else {\n            setErrorMessage('');\n        }\n    };\n\n    return (\n        <>\n            <ComponentDemo title=\"Input with Validation\">\n                <div className=\"w-full max-w-sm\">\n                    <TextInput\n                        label=\"Username\"\n                        placeholder=\"Enter username\"\n                        value={validatedValue}\n                        onChange={handleValidatedChange}\n                        error={errorMessage}\n                    />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default Validation;\n"
        },
        {
          "title": "WithIcons",
          "code": "import React from 'react';\nimport { TextInput as TextInputRaw } from '../../../components';\nimport { withFieldLabel } from '../../../utils/field-label';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst TextInput = withFieldLabel(TextInputRaw);\n\nconst code = `<TextInput\n  label=\"Search\"\n  placeholder=\"Search...\"\n  rightIcon={<span>🔍</span>}\n  value={value}\n  onChange={(e) => setValue(e.value)}\n/>\n<TextInput\n  label=\"Email\"\n  placeholder=\"user@example.com\"\n  leftIcon={<span>✉</span>}\n  value={value}\n  onChange={(e) => setValue(e.value)}\n/>`;\n\nconst WithIcons: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo title=\"Text Input with Icons\">\n                <div className=\"w-full max-w-sm space-y-4\">\n                    <TextInput label=\"Search\" placeholder=\"Search...\" rightIcon={<span>🔍</span>} />\n                    <TextInput label=\"Email\" placeholder=\"user@example.com\" leftIcon={<span>✉</span>} />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default WithIcons;\n"
        },
        {
          "title": "WithLabel",
          "code": "import React, { useState } from 'react';\nimport { TextInput as TextInputRaw } from '../../../components';\nimport { withFieldLabel } from '../../../utils/field-label';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst TextInput = withFieldLabel(TextInputRaw);\n\nconst code = `<TextInput\n  label=\"Full Name\"\n  placeholder=\"John Doe\"\n/>`;\n\nconst WithLabel: React.FC = () => {\n    const [withLabelValue, setWithLabelValue] = useState('');\n\n    return (\n        <>\n            <ComponentDemo title=\"Text Input with Label\">\n                <div className=\"w-full max-w-sm\">\n                    <TextInput\n                        label=\"Full Name\"\n                        placeholder=\"John Doe\"\n                        value={withLabelValue}\n                        onChange={(e) => setWithLabelValue(e.value)}\n                    />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default WithLabel;\n"
        }
      ],
      "props": {
        "textInputProps": {
          "value": {
            "type": "string",
            "description": "Current value of the input (controlled)"
          },
          "placeholder": {
            "type": "string",
            "description": "Placeholder text"
          },
          "label": {
            "type": "string",
            "description": "Label text"
          },
          "error": {
            "type": "string | boolean",
            "description": "Error message string (also marks field invalid). Pass `true` to mark invalid without a message"
          },
          "invalid": {
            "type": "boolean",
            "description": "Force the field into an invalid state without an error message"
          },
          "helperText": {
            "type": "ReactNode",
            "description": "Helper text rendered under the input and linked via aria-describedby"
          },
          "clearable": {
            "type": "boolean",
            "default": "false",
            "description": "Show an X button to clear the input value"
          },
          "onClear": {
            "type": "() => void",
            "description": "Callback fired after the value is cleared via the clear button"
          },
          "disabled": {
            "type": "boolean",
            "default": false,
            "description": "Disable the input"
          },
          "readonly": {
            "type": "boolean",
            "default": false,
            "description": "Make the input read-only"
          },
          "required": {
            "type": "boolean",
            "default": false,
            "description": "Mark the input as required"
          },
          "autoFocus": {
            "type": "boolean",
            "default": false,
            "description": "Auto focus the input on mount"
          },
          "maxLength": {
            "type": "number",
            "description": "Maximum character limit"
          },
          "minLength": {
            "type": "number",
            "description": "Minimum character requirement"
          },
          "pattern": {
            "type": "string",
            "description": "Regex pattern for validation"
          },
          "autoComplete": {
            "type": "string",
            "description": "Auto-complete hint"
          },
          "leftIcon": {
            "type": "ReactNode",
            "description": "Icon to display on the left side"
          },
          "rightIcon": {
            "type": "ReactNode",
            "description": "Icon to display on the right side"
          },
          "id": {
            "type": "string",
            "description": "Unique identifier for the input"
          },
          "name": {
            "type": "string",
            "description": "Name attribute for the input"
          },
          "onChange": {
            "type": "function",
            "description": "Change event handler"
          },
          "className": {
            "type": "string",
            "description": "Additional CSS classes"
          }
        }
      },
      "storyDir": "text-input"
    },
    "Textarea": {
      "name": "Textarea",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "AutoResize",
          "code": "import React, { useState } from 'react';\nimport { TextArea as TextAreaRaw } from '../../../components';\nimport { withFieldLabel } from '../../../utils/field-label';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst TextArea = withFieldLabel(TextAreaRaw);\n\nconst code = `<TextArea\n  label=\"Comments\"\n  placeholder=\"Start typing and watch it grow...\"\n  value={value}\n  onChange={(e) => setValue(e.target.value)}\n  autoResize\n  rows={2}\n/>`;\n\nconst AutoResize: React.FC = () => {\n    const [autoResizeValue, setAutoResizeValue] = useState('');\n\n    return (\n        <>\n            <ComponentDemo title=\"Auto-resizing TextArea\">\n                <div className=\"w-full max-w-sm\">\n                    <TextArea\n                        label=\"Comments\"\n                        placeholder=\"Start typing and watch it grow...\"\n                        value={autoResizeValue}\n                        onChange={(e) => setAutoResizeValue(e.value)}\n                        autoResize\n                        rows={2}\n                    />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default AutoResize;\n"
        },
        {
          "title": "BasicUsage",
          "code": "import React, { useState } from 'react';\nimport { TextArea as TextAreaRaw } from '../../../components';\nimport { withFieldLabel } from '../../../utils/field-label';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst TextArea = withFieldLabel(TextAreaRaw);\n\nconst code = `import { TextArea } from 'fluxo-ui';\n\nfunction MyComponent() {\n  const [value, setValue] = useState('');\n\n  return (\n    <TextArea\n      label=\"Description\"\n      placeholder=\"Enter your description...\"\n      value={value}\n      onChange={(e) => setValue(e.target.value)}\n    />\n  );\n}`;\n\nconst BasicUsage: React.FC = () => {\n    const [basicValue, setBasicValue] = useState('');\n\n    return (\n        <>\n            <ComponentDemo title=\"Basic TextArea\">\n                <div className=\"w-full max-w-sm\">\n                    <TextArea\n                        label=\"Description\"\n                        placeholder=\"Enter your description...\"\n                        value={basicValue}\n                        onChange={(e) => setBasicValue(e.value)}\n                    />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock title=\"Basic Example\" code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "CharacterLimit",
          "code": "import React, { useState } from 'react';\nimport { TextArea as TextAreaRaw } from '../../../components';\nimport { withFieldLabel } from '../../../utils/field-label';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst TextArea = withFieldLabel(TextAreaRaw);\n\nconst code = `<TextArea\n  label=\"Bio\"\n  placeholder=\"Tell us about yourself...\"\n  value={value}\n  onChange={(e) => setValue(e.value)}\n  maxLength={150}\n/>`;\n\nconst CharacterLimit: React.FC = () => {\n    const [countedValue, setCountedValue] = useState('');\n\n    return (\n        <>\n            <ComponentDemo title=\"TextArea with Character Limit\">\n                <div className=\"w-full max-w-sm\">\n                    <TextArea\n                        label=\"Bio\"\n                        placeholder=\"Tell us about yourself...\"\n                        value={countedValue}\n                        onChange={(e) => setCountedValue(e.value)}\n                        maxLength={150}\n                    />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default CharacterLimit;\n"
        },
        {
          "title": "RowHeights",
          "code": "import React from 'react';\nimport { TextArea as TextAreaRaw } from '../../../components';\nimport { withFieldLabel } from '../../../utils/field-label';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst TextArea = withFieldLabel(TextAreaRaw);\n\nconst code = `<TextArea label=\"Short (2 rows)\" rows={2} placeholder=\"2 rows high\" />\n<TextArea label=\"Medium (4 rows)\" rows={4} placeholder=\"4 rows high\" />\n<TextArea label=\"Tall (8 rows)\" rows={8} placeholder=\"8 rows high\" />`;\n\nconst RowHeights: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo title=\"Different Row Heights\">\n                <div className=\"w-full max-w-sm space-y-4\">\n                    <TextArea label=\"Short (2 rows)\" rows={2} placeholder=\"2 rows high\" />\n                    <TextArea label=\"Medium (4 rows)\" rows={4} placeholder=\"4 rows high\" />\n                    <TextArea label=\"Tall (8 rows)\" rows={8} placeholder=\"8 rows high\" />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default RowHeights;\n"
        },
        {
          "title": "TextAreaStates",
          "code": "import React from 'react';\nimport { TextArea as TextAreaRaw } from '../../../components';\nimport { withFieldLabel } from '../../../utils/field-label';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst TextArea = withFieldLabel(TextAreaRaw);\n\nconst code = `<TextArea label=\"Normal\" placeholder=\"Normal state\" value={value} onChange={(e) => setValue(e.value)} />\n<TextArea label=\"Disabled\" placeholder=\"Disabled state\" value={value} onChange={(e) => setValue(e.value)} disabled />\n<TextArea label=\"Read Only\" value=\"This is read-only content\" readonly onChange={(e) => setValue(e.value)} />\n<TextArea label=\"Required\" placeholder=\"Required field\" value={value} onChange={(e) => setValue(e.value)} required />\n<TextArea label=\"With Error\" error=\"This field is required\" value={value} onChange={(e) => setValue(e.value)} />`;\n\nconst TextAreaStates: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo title=\"TextArea States\">\n                <div className=\"w-full max-w-sm space-y-4\">\n                    <TextArea label=\"Normal\" placeholder=\"Normal state\" />\n                    <TextArea label=\"Disabled\" placeholder=\"Disabled state\" disabled />\n                    <TextArea label=\"Read Only\" value=\"This is read-only content\" readonly />\n                    <TextArea label=\"Required\" placeholder=\"Required field\" required />\n                    <TextArea label=\"With Error\" error=\"This field is required\" />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default TextAreaStates;\n"
        }
      ],
      "props": {
        "textAreaProps": {
          "value": {
            "type": "string",
            "description": "Current value of the textarea (controlled)"
          },
          "placeholder": {
            "type": "string",
            "description": "Placeholder text"
          },
          "label": {
            "type": "string",
            "description": "Label text"
          },
          "error": {
            "type": "string | boolean",
            "description": "Error message string (also marks invalid). Pass `true` to mark invalid without a message"
          },
          "invalid": {
            "type": "boolean",
            "description": "Force the field into an invalid state without an error message"
          },
          "helperText": {
            "type": "ReactNode",
            "description": "Helper text rendered under the input and linked via aria-describedby"
          },
          "disabled": {
            "type": "boolean",
            "default": false,
            "description": "Disable the textarea"
          },
          "readonly": {
            "type": "boolean",
            "default": false,
            "description": "Make the textarea read-only"
          },
          "required": {
            "type": "boolean",
            "default": false,
            "description": "Mark the textarea as required"
          },
          "autoFocus": {
            "type": "boolean",
            "default": false,
            "description": "Auto focus the textarea on mount"
          },
          "rows": {
            "type": "number",
            "default": 3,
            "description": "Number of visible rows"
          },
          "autoResize": {
            "type": "boolean",
            "default": false,
            "description": "Auto resize height based on content"
          },
          "maxHeight": {
            "type": "string",
            "default": "200px",
            "description": "Maximum height for auto-resizing"
          },
          "maxLength": {
            "type": "number",
            "description": "Maximum character limit"
          },
          "minLength": {
            "type": "number",
            "description": "Minimum character requirement"
          },
          "id": {
            "type": "string",
            "description": "Unique identifier for the textarea"
          },
          "name": {
            "type": "string",
            "description": "Name attribute for the textarea"
          },
          "onChange": {
            "type": "function",
            "description": "Change event handler"
          },
          "className": {
            "type": "string",
            "description": "Additional CSS classes"
          }
        }
      },
      "storyDir": "textarea"
    },
    "ToggleButton": {
      "name": "ToggleButton",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import cn from 'classnames';\nimport React, { useState } from 'react';\nimport { ToggleButton } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\n\nconst code = `import { ToggleButton } from 'fluxo-ui';\n\nfunction MyComponent() {\n  const [checked, setChecked] = useState(false);\n\n  return (\n    <ToggleButton\n      checked={checked}\n      onChange={(e) => setChecked(e.value)}\n    />\n  );\n}`;\n\nconst BasicUsage: React.FC = () => {\n    const { isDark } = useStoryTheme();\n    const [basicToggle, setBasicToggle] = useState(false);\n\n    return (\n        <>\n            <ComponentDemo title=\"Default Toggle Button\">\n                <div className=\"flex flex-col items-center gap-4\">\n                    <ToggleButton checked={basicToggle} onChange={(e) => setBasicToggle(e.value)} />\n                    <p className={cn('text-sm', { 'text-gray-400': isDark, 'text-gray-600': !isDark })}>\n                        Current state: {basicToggle ? 'On' : 'Off'}\n                    </p>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock title=\"Basic Example\" code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "CustomLabels",
          "code": "import cn from 'classnames';\nimport React, { useState } from 'react';\nimport { ToggleButton } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\n\nconst code = `<ToggleButton\n  checked={checked}\n  onChange={(e) => setChecked(e.value)}\n  onLabel=\"Enabled\"\n  offLabel=\"Disabled\"\n/>`;\n\nconst CustomLabels: React.FC = () => {\n    const { isDark } = useStoryTheme();\n    const [customLabelsToggle, setCustomLabelsToggle] = useState(false);\n\n    return (\n        <>\n            <ComponentDemo title=\"Toggle Button with Custom Labels\">\n                <div className=\"flex flex-col items-center gap-4\">\n                    <ToggleButton\n                        checked={customLabelsToggle}\n                        onChange={(e) => setCustomLabelsToggle(e.value)}\n                        onLabel=\"Enabled\"\n                        offLabel=\"Disabled\"\n                    />\n                    <p className={cn('text-sm', { 'text-gray-400': isDark, 'text-gray-600': !isDark })}>Feature is {customLabelsToggle ? 'enabled' : 'disabled'}</p>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default CustomLabels;\n"
        },
        {
          "title": "CustomStyling",
          "code": "import React from 'react';\nimport { ToggleButton } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<ToggleButton\n  checked={true}\n  onLabel=\"Active\"\n  offLabel=\"Inactive\"\n  variant=\"success\"\n  className=\"font-bold\"\n/>\n\n<ToggleButton\n  checked={false}\n  onLabel=\"Yes\"\n  offLabel=\"No\"\n  variant=\"primary\"\n  size=\"lg\"\n/>`;\n\nconst CustomStyling: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo title=\"Customized Toggle Buttons\">\n                <div className=\"flex flex-wrap gap-4\">\n                    <ToggleButton checked={true} onLabel=\"Active\" offLabel=\"Inactive\" variant=\"success\" className=\"font-bold\" />\n                    <ToggleButton checked={false} onLabel=\"Yes\" offLabel=\"No\" variant=\"primary\" size=\"lg\" />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default CustomStyling;\n"
        },
        {
          "title": "EventHandling",
          "code": "import cn from 'classnames';\nimport React, { useState } from 'react';\nimport { ToggleButton } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\n\nconst code = `const handleToggle = (e) => {\n  console.log('Toggle value:', e.value);\n  console.log('Toggle name:', e.name);\n  console.log('Additional args:', e.args);\n  console.log('Original event:', e.event);\n\n  setChecked(e.value);\n};\n\n<ToggleButton\n  checked={checked}\n  onChange={handleToggle}\n  name=\"feature-toggle\"\n  args={{ feature: 'example' }}\n/>`;\n\nconst EventHandling: React.FC = () => {\n    const { isDark } = useStoryTheme();\n    const [toggleValue, setToggleValue] = useState(false);\n\n    return (\n        <>\n            <ComponentDemo title=\"Toggle with Event Logging\">\n                <div className=\"flex flex-col items-center gap-4 w-full\">\n                    <ToggleButton\n                        checked={toggleValue}\n                        onChange={(e) => {\n                            console.log('Toggle changed:', e);\n                            setToggleValue(e.value);\n                        }}\n                        onLabel=\"Active\"\n                        offLabel=\"Inactive\"\n                        name=\"feature-toggle\"\n                        args={{ feature: 'example' }}\n                    />\n                    <div className={cn('p-4 rounded-lg w-full max-w-md', { 'bg-gray-800': isDark, 'bg-gray-100': !isDark })}>\n                        <p className={cn('text-sm mb-2', { 'text-gray-400': isDark, 'text-gray-600': !isDark })}>Event details (check console):</p>\n                        <pre className={cn('text-xs', { 'text-gray-300': isDark, 'text-gray-700': !isDark })}>\n                            {JSON.stringify(\n                                {\n                                    value: toggleValue,\n                                    name: 'feature-toggle',\n                                    args: { feature: 'example' },\n                                },\n                                null,\n                                2\n                            )}\n                        </pre>\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default EventHandling;\n"
        },
        {
          "title": "FormIntegration",
          "code": "import cn from 'classnames';\nimport React, { useState } from 'react';\nimport { ToggleButton } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\n\nconst code = `<form onSubmit={handleSubmit}>\n  <ToggleButton\n    name=\"terms-accepted\"\n    checked={accepted}\n    onChange={(e) => setAccepted(e.value)}\n  />\n  <button type=\"submit\">Submit</button>\n</form>\n\n// The toggle value is available in form data as a string\n// FormData will contain: terms-accepted: \"true\" or \"false\"`;\n\nconst FormIntegration: React.FC = () => {\n    const { isDark } = useStoryTheme();\n    const [formToggle, setFormToggle] = useState(false);\n\n    return (\n        <>\n            <ComponentDemo title=\"Toggle Button in Forms\">\n                <form\n                    className=\"w-full max-w-md space-y-4\"\n                    onSubmit={(e) => {\n                        e.preventDefault();\n                        const formData = new FormData(e.currentTarget);\n                        alert(`Form submitted with: ${formData.get('terms-accepted')}`);\n                    }}\n                >\n                    <div className={cn('flex items-center justify-between p-4 rounded-lg', { 'bg-gray-800': isDark, 'bg-gray-100': !isDark })}>\n                        <label htmlFor=\"terms-toggle\" className={cn({ 'text-gray-100': isDark, 'text-gray-900': !isDark })}>\n                            Accept Terms and Conditions\n                        </label>\n                        <ToggleButton\n                            id=\"terms-toggle\"\n                            name=\"terms-accepted\"\n                            checked={formToggle}\n                            onChange={(e) => setFormToggle(e.value)}\n                        />\n                    </div>\n                    <button\n                        type=\"submit\"\n                        className=\"w-full bg-blue-600 text-white px-4 py-2 rounded-lg hover:bg-blue-700 transition-colors\"\n                    >\n                        Submit Form\n                    </button>\n                </form>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default FormIntegration;\n"
        },
        {
          "title": "MultipleToggles",
          "code": "import cn from 'classnames';\nimport React, { useState } from 'react';\nimport { ToggleButton } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\n\nconst code = `const [settings, setSettings] = useState({\n  darkMode: false,\n  notifications: true,\n  autoSave: false,\n});\n\nconst handleToggle = (key) => (e) => {\n  setSettings(prev => ({ ...prev, [key]: e.value }));\n};\n\n<div className=\"space-y-4\">\n  <div className=\"flex items-center justify-between\">\n    <span>Dark Mode</span>\n    <ToggleButton\n      checked={settings.darkMode}\n      onChange={handleToggle('darkMode')}\n    />\n  </div>\n  <div className=\"flex items-center justify-between\">\n    <span>Notifications</span>\n    <ToggleButton\n      checked={settings.notifications}\n      onChange={handleToggle('notifications')}\n    />\n  </div>\n  <div className=\"flex items-center justify-between\">\n    <span>Auto-Save</span>\n    <ToggleButton\n      checked={settings.autoSave}\n      onChange={handleToggle('autoSave')}\n    />\n  </div>\n</div>`;\n\nconst MultipleToggles: React.FC = () => {\n    const { isDark } = useStoryTheme();\n    const [multipleToggles, setMultipleToggles] = useState({\n        feature1: false,\n        feature2: true,\n        feature3: false,\n    });\n\n    const handleMultipleToggle = (key: string) => (e: { value: boolean }) => {\n        setMultipleToggles((prev) => ({ ...prev, [key]: e.value }));\n    };\n\n    return (\n        <>\n            <ComponentDemo title=\"Managing Multiple Toggles\">\n                <div className=\"space-y-4 w-full max-w-md\">\n                    <div className={cn('flex items-center justify-between p-4 rounded-lg', { 'bg-gray-800': isDark, 'bg-gray-100': !isDark })}>\n                        <div>\n                            <h4 className={cn('font-medium', { 'text-gray-100': isDark, 'text-gray-900': !isDark })}>Dark Mode</h4>\n                            <p className={cn('text-sm', { 'text-gray-400': isDark, 'text-gray-600': !isDark })}>Enable dark theme</p>\n                        </div>\n                        <ToggleButton\n                            checked={multipleToggles.feature1}\n                            onChange={handleMultipleToggle('feature1')}\n                            onLabel=\"On\"\n                            offLabel=\"Off\"\n                        />\n                    </div>\n                    <div className={cn('flex items-center justify-between p-4 rounded-lg', { 'bg-gray-800': isDark, 'bg-gray-100': !isDark })}>\n                        <div>\n                            <h4 className={cn('font-medium', { 'text-gray-100': isDark, 'text-gray-900': !isDark })}>Notifications</h4>\n                            <p className={cn('text-sm', { 'text-gray-400': isDark, 'text-gray-600': !isDark })}>Receive email notifications</p>\n                        </div>\n                        <ToggleButton\n                            checked={multipleToggles.feature2}\n                            onChange={handleMultipleToggle('feature2')}\n                            onLabel=\"On\"\n                            offLabel=\"Off\"\n                        />\n                    </div>\n                    <div className={cn('flex items-center justify-between p-4 rounded-lg', { 'bg-gray-800': isDark, 'bg-gray-100': !isDark })}>\n                        <div>\n                            <h4 className={cn('font-medium', { 'text-gray-100': isDark, 'text-gray-900': !isDark })}>Auto-Save</h4>\n                            <p className={cn('text-sm', { 'text-gray-400': isDark, 'text-gray-600': !isDark })}>Automatically save changes</p>\n                        </div>\n                        <ToggleButton\n                            checked={multipleToggles.feature3}\n                            onChange={handleMultipleToggle('feature3')}\n                            onLabel=\"On\"\n                            offLabel=\"Off\"\n                        />\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default MultipleToggles;\n"
        },
        {
          "title": "Sizes",
          "code": "import React from 'react';\nimport { ToggleButton } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<ToggleButton checked={true} size=\"xs\" onLabel=\"XS\" />\n<ToggleButton checked={true} size=\"sm\" onLabel=\"Small\" />\n<ToggleButton checked={true} size=\"md\" onLabel=\"Medium\" />\n<ToggleButton checked={true} size=\"lg\" onLabel=\"Large\" />\n<ToggleButton checked={true} size=\"xl\" onLabel=\"XL\" />`;\n\nconst Sizes: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo title=\"Toggle Button Sizes\">\n                <div className=\"flex flex-wrap items-center gap-4\">\n                    <ToggleButton checked={true} size=\"xs\" onLabel=\"XS\" />\n                    <ToggleButton checked={true} size=\"sm\" onLabel=\"Small\" />\n                    <ToggleButton checked={true} size=\"md\" onLabel=\"Medium\" />\n                    <ToggleButton checked={true} size=\"lg\" onLabel=\"Large\" />\n                    <ToggleButton checked={true} size=\"xl\" onLabel=\"XL\" />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default Sizes;\n"
        },
        {
          "title": "States",
          "code": "import cn from 'classnames';\nimport React from 'react';\nimport { ToggleButton } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\n\nconst code = `<ToggleButton checked={false} />\n<ToggleButton checked={true} />\n<ToggleButton checked={false} disabled />\n<ToggleButton checked={true} disabled />`;\n\nconst States: React.FC = () => {\n    const { isDark } = useStoryTheme();\n\n    return (\n        <>\n            <ComponentDemo title=\"Toggle Button States\">\n                <div className=\"flex flex-wrap gap-4\">\n                    <div className=\"flex flex-col items-center gap-2\">\n                        <ToggleButton checked={false} />\n                        <span className={cn('text-sm', { 'text-gray-400': isDark, 'text-gray-600': !isDark })}>Off State</span>\n                    </div>\n                    <div className=\"flex flex-col items-center gap-2\">\n                        <ToggleButton checked={true} />\n                        <span className={cn('text-sm', { 'text-gray-400': isDark, 'text-gray-600': !isDark })}>On State</span>\n                    </div>\n                    <div className=\"flex flex-col items-center gap-2\">\n                        <ToggleButton checked={false} disabled />\n                        <span className={cn('text-sm', { 'text-gray-400': isDark, 'text-gray-600': !isDark })}>Disabled Off</span>\n                    </div>\n                    <div className=\"flex flex-col items-center gap-2\">\n                        <ToggleButton checked={true} disabled />\n                        <span className={cn('text-sm', { 'text-gray-400': isDark, 'text-gray-600': !isDark })}>Disabled On</span>\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default States;\n"
        },
        {
          "title": "Variants",
          "code": "import React from 'react';\nimport { ToggleButton } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<ToggleButton checked={true} variant=\"primary\" onLabel=\"Primary\" />\n<ToggleButton checked={true} variant=\"success\" onLabel=\"Success\" />\n<ToggleButton checked={true} variant=\"warning\" onLabel=\"Warning\" />\n<ToggleButton checked={true} variant=\"danger\" onLabel=\"Danger\" />\n<ToggleButton checked={true} variant=\"info\" onLabel=\"Info\" />\n<ToggleButton checked={true} variant=\"secondary\" onLabel=\"Secondary\" />`;\n\nconst Variants: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo title=\"Toggle Button Variants\">\n                <div className=\"grid grid-cols-2 gap-4\">\n                    <ToggleButton checked={true} variant=\"primary\" onLabel=\"Primary\" />\n                    <ToggleButton checked={true} variant=\"success\" onLabel=\"Success\" />\n                    <ToggleButton checked={true} variant=\"warning\" onLabel=\"Warning\" />\n                    <ToggleButton checked={true} variant=\"danger\" onLabel=\"Danger\" />\n                    <ToggleButton checked={true} variant=\"info\" onLabel=\"Info\" />\n                    <ToggleButton checked={true} variant=\"secondary\" onLabel=\"Secondary\" />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default Variants;\n"
        }
      ],
      "props": {
        "toggleButtonProps": {
          "checked": {
            "type": "boolean",
            "default": "false",
            "description": "The checked state of the toggle button"
          },
          "onChange": {
            "type": "(event: ComponentEvent<boolean>) => void",
            "description": "Callback fired when the toggle state changes. Receives ComponentEvent with value, name, args, and event."
          },
          "onLabel": {
            "type": "string",
            "default": "'On'",
            "description": "Label to display when button is checked/on"
          },
          "offLabel": {
            "type": "string",
            "default": "'Off'",
            "description": "Label to display when button is unchecked/off"
          },
          "disabled": {
            "type": "boolean",
            "default": "false",
            "description": "Disable the toggle button interaction"
          },
          "className": {
            "type": "string",
            "description": "Additional CSS classes"
          },
          "name": {
            "type": "string",
            "description": "Name attribute for form submission"
          },
          "id": {
            "type": "string",
            "description": "HTML id attribute (auto-generated if not provided)"
          },
          "args": {
            "type": "any",
            "description": "Additional arguments passed to onChange event"
          },
          "variant": {
            "type": "'success' | 'warning' | 'danger' | 'info' | 'default' | 'primary' | 'secondary'",
            "description": "Color variant for the button (from BaseComponentProps)"
          },
          "size": {
            "type": "'xs' | 'sm' | 'md' | 'lg' | 'xl'",
            "description": "Size of the button (from BaseComponentProps)"
          }
        }
      },
      "storyDir": "toggle-button"
    },
    "Accordion": {
      "name": "Accordion",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React from 'react';\nimport { Accordion } from '../../../components';\nimport type { AccordionItemDef } from '../../../components/accordion';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst items: AccordionItemDef[] = [\n    {\n        id: 'overview',\n        title: 'What is FluxoUI?',\n        content: 'FluxoUI is a React component library built with TypeScript, Vite, and Tailwind CSS v4. It ships tree-shakable components with TypeScript types, hooks, icons, and a custom state-management store.',\n    },\n    {\n        id: 'install',\n        title: 'Installation',\n        content: 'Install via npm: `npm install fluxo-ui`. Then import the components you need and include the stylesheet once at your app root.',\n    },\n    {\n        id: 'theming',\n        title: 'Theming',\n        content: 'FluxoUI uses CSS custom properties for all themeable values. Five brand themes plus dark mode are available out of the box via body classes.',\n    },\n];\n\nconst code = `import { Accordion } from 'fluxo-ui';\n\n<Accordion items={items} mode=\"single\" defaultOpen={['overview']} />`;\n\nconst BasicUsage: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Basic Accordion\" description=\"Single-open mode.\">\n            <div style={{ width: '100%', maxWidth: 640 }}>\n                <Accordion items={items} mode=\"single\" defaultOpen={['overview']} />\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default BasicUsage;\n"
        },
        {
          "title": "Modes",
          "code": "import React from 'react';\nimport { Accordion } from '../../../components';\nimport type { AccordionItemDef } from '../../../components/accordion';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst items: AccordionItemDef[] = [\n    { id: 'q1', title: 'Can I open multiple panels?', content: 'Yes — set mode=\"multi\" to allow any number of panels open at once.' },\n    { id: 'q2', title: 'Is it keyboard accessible?', content: 'Arrow up/down moves focus between headers, Home/End jump to the ends, Space/Enter toggles a panel.' },\n    { id: 'q3', title: 'Can items be disabled?', content: 'Yes — set disabled on the item. The header becomes un-focusable and un-togglable.', disabled: true },\n];\n\nconst code = `<Accordion items={items} mode=\"multi\" defaultOpen={['q1', 'q2']} />\n<Accordion items={items} mode=\"single\" chevronPosition=\"left\" />`;\n\nconst Modes: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Multi Mode & Chevron Position\" description=\"Multi expand and left chevron.\">\n            <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 22, maxWidth: 640 }}>\n                <div>\n                    <div style={{ fontSize: 12, marginBottom: 6, color: 'var(--eui-text-muted)' }}>Multi mode</div>\n                    <Accordion items={items} mode=\"multi\" variant=\"bordered\" defaultOpen={['q1', 'q2']} />\n                </div>\n                <div>\n                    <div style={{ fontSize: 12, marginBottom: 6, color: 'var(--eui-text-muted)' }}>Chevron on left</div>\n                    <Accordion items={items} mode=\"single\" variant=\"minimal\" chevronPosition=\"left\" />\n                </div>\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default Modes;\n"
        },
        {
          "title": "Variants",
          "code": "import React from 'react';\nimport { Accordion } from '../../../components';\nimport type { AccordionItemDef, AccordionVariant } from '../../../components/accordion';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst items: AccordionItemDef[] = [\n    { id: 'a', title: 'Section A', content: 'Content for section A.' },\n    { id: 'b', title: 'Section B', content: 'Content for section B.' },\n    { id: 'c', title: 'Section C', content: 'Content for section C.' },\n];\n\nconst variants: AccordionVariant[] = ['default', 'bordered', 'filled', 'minimal', 'separated'];\n\nconst code = `<Accordion items={items} variant=\"bordered\" />\n<Accordion items={items} variant=\"filled\" />\n<Accordion items={items} variant=\"separated\" />`;\n\nconst Variants: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Variants\" description=\"Five visual styles for different contexts.\">\n            <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 24 }}>\n                {variants.map((v) => (\n                    <div key={v}>\n                        <div style={{ fontSize: 12, marginBottom: 6, color: 'var(--eui-text-muted)', textTransform: 'capitalize' }}>{v}</div>\n                        <Accordion items={items} variant={v} defaultOpen={['a']} />\n                    </div>\n                ))}\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default Variants;\n"
        }
      ],
      "props": {
        "accordionProps": {
          "items": {
            "type": "AccordionItemDef[]",
            "description": "Array of { id, title, content, icon?, disabled? }."
          },
          "mode": {
            "type": "'single' | 'multi'",
            "default": "'single'",
            "description": "Whether multiple panels can be open at once."
          },
          "variant": {
            "type": "'default' | 'bordered' | 'filled' | 'minimal' | 'separated'",
            "default": "'default'",
            "description": "Visual style."
          },
          "chevronPosition": {
            "type": "'left' | 'right'",
            "default": "'right'",
            "description": "Where the expand chevron appears in the header."
          },
          "defaultOpen": {
            "type": "string[]",
            "description": "Initial open item ids (uncontrolled)."
          },
          "value": {
            "type": "string[]",
            "description": "Controlled open item ids."
          },
          "onChange": {
            "type": "(openIds: string[]) => void",
            "description": "Called when the set of open items changes."
          },
          "ariaLabel": {
            "type": "string",
            "description": "Accessible name for the accordion if needed."
          },
          "headingLevel": {
            "type": "1 | 2 | 3 | 4 | 5 | 6",
            "default": "3",
            "description": "Heading level used for each item title (h1-h6) so the page heading outline is correct."
          },
          "unmountOnCollapse": {
            "type": "boolean",
            "default": "false",
            "description": "Unmount panel content when collapsed (useful for heavy content that should not stay in the DOM)."
          },
          "className": {
            "type": "string",
            "description": "Additional CSS class for the accordion wrapper."
          }
        }
      },
      "storyDir": "accordion"
    },
    "ActionSheet": {
      "name": "ActionSheet",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React, { useState } from 'react';\nimport { ActionSheet, Button } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { ActionSheet, Button } from 'fluxo-ui';\n\nconst [open, setOpen] = useState(false);\n\n<Button label=\"Share…\" onClick={() => setOpen(true)} />\n<ActionSheet\n    open={open}\n    onClose={() => setOpen(false)}\n    title=\"Share photo\"\n    actions={[\n        { label: 'Copy link', onSelect: copyLink },\n        { label: 'Save to Files', onSelect: save },\n        { label: 'Delete', destructive: true, onSelect: remove },\n    ]}\n/>`;\n\nconst noteBox: React.CSSProperties = {\n    padding: '10px 14px',\n    background: 'var(--eui-bg-subtle)',\n    border: '1px solid var(--eui-border-subtle)',\n    borderRadius: 6,\n    fontSize: 12,\n    color: 'var(--eui-text-muted)',\n};\n\nconst BasicUsage: React.FC = () => {\n    const [open, setOpen] = useState(false);\n    const [last, setLast] = useState<string | null>(null);\n\n    return (\n        <>\n            <ComponentDemo title=\"Tap to open\" description=\"Each action runs its onSelect handler and the sheet auto-closes.\">\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16 }}>\n                    <div>\n                        <Button label=\"Open action sheet\" onClick={() => setOpen(true)} />\n                    </div>\n                    <div style={noteBox}>Last action: <strong style={{ color: 'var(--eui-text)' }}>{last ?? '—'}</strong></div>\n                </div>\n                <ActionSheet\n                    open={open}\n                    onClose={() => setOpen(false)}\n                    title=\"Share photo\"\n                    message=\"Choose what to do with the selected photo.\"\n                    actions={[\n                        { label: 'Copy link', onSelect: () => setLast('Copy link') },\n                        { label: 'Save to Files', onSelect: () => setLast('Save to Files') },\n                        { label: 'Move to album', onSelect: () => setLast('Move to album') },\n                        { label: 'Delete', destructive: true, onSelect: () => setLast('Delete') },\n                    ]}\n                />\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "DestructiveStates",
          "code": "import React, { useState } from 'react';\nimport { ActionSheet, Button } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<ActionSheet\n    open={open}\n    onClose={close}\n    title=\"Account\"\n    actions={[\n        { label: 'Switch account' },\n        { label: 'Sign out', destructive: true, onSelect: signOut },\n        { label: 'Delete account', destructive: true, disabled: true, description: 'Pending verification' },\n    ]}\n/>`;\n\nconst DestructiveStates: React.FC = () => {\n    const [open, setOpen] = useState(false);\n    return (\n        <>\n            <ComponentDemo title=\"Destructive & disabled\" description=\"Mark a single action as destructive for the danger color, disabled for non-interactive rows, and add a description for context.\">\n                <Button label=\"Open destructive sheet\" variant=\"danger\" onClick={() => setOpen(true)} />\n                <ActionSheet open={open} onClose={() => setOpen(false)} title=\"Account\" actions={[\n                    { label: 'Switch account' },\n                    { label: 'Sign out', destructive: true },\n                    { label: 'Delete account', destructive: true, disabled: true, description: 'Pending verification' },\n                ]} />\n            </ComponentDemo>\n            <div className=\"mt-4\"><CodeBlock code={code} language=\"tsx\" /></div>\n        </>\n    );\n};\n\nexport default DestructiveStates;\n"
        },
        {
          "title": "Variants",
          "code": "import React, { useState } from 'react';\nimport { ActionSheet, Button } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst iosCode = `<ActionSheet\n    open={open}\n    onClose={close}\n    variant=\"ios\"\n    actions={[\n        { label: 'Reply', onSelect: reply },\n        { label: 'Forward', onSelect: forward },\n    ]}\n/>`;\n\nconst materialCode = `<ActionSheet\n    open={open}\n    onClose={close}\n    variant=\"material\"\n    title=\"Add new\"\n    actions={[\n        { label: 'New folder', onSelect: ... },\n        { label: 'New document', onSelect: ... },\n    ]}\n/>`;\n\nconst plainCode = `<ActionSheet\n    open={open}\n    onClose={close}\n    variant=\"plain\"\n    actions={[\n        { label: 'Mark as read', onSelect: ... },\n        { label: 'Archive', onSelect: ... },\n    ]}\n/>`;\n\nconst Variants: React.FC = () => {\n    const [ios, setIos] = useState(false);\n    const [mat, setMat] = useState(false);\n    const [plain, setPlain] = useState(false);\n\n    return (\n        <>\n            <ComponentDemo title=\"iOS variant\" description=\"Centered actions card with a separate cancel pill — the default.\">\n                <Button label=\"Open iOS sheet\" onClick={() => setIos(true)} />\n                <ActionSheet open={ios} onClose={() => setIos(false)} variant=\"ios\" actions={[\n                    { label: 'Reply' }, { label: 'Forward' }, { label: 'Mark as unread' },\n                ]} />\n            </ComponentDemo>\n            <div className=\"mt-4\"><CodeBlock code={iosCode} language=\"tsx\" /></div>\n\n            <ComponentDemo title=\"Material variant\" description=\"Edge-to-edge bottom sheet with left-aligned rows.\" className=\"mt-4\">\n                <Button label=\"Open Material sheet\" variant=\"secondary\" onClick={() => setMat(true)} />\n                <ActionSheet open={mat} onClose={() => setMat(false)} variant=\"material\" title=\"Add new\" actions={[\n                    { label: 'New folder' }, { label: 'New document' }, { label: 'Upload file' },\n                ]} />\n            </ComponentDemo>\n            <div className=\"mt-4\"><CodeBlock code={materialCode} language=\"tsx\" /></div>\n\n            <ComponentDemo title=\"Plain variant\" description=\"Merges the cancel button into the same card.\" className=\"mt-4\">\n                <Button label=\"Open plain sheet\" variant=\"info\" onClick={() => setPlain(true)} />\n                <ActionSheet open={plain} onClose={() => setPlain(false)} variant=\"plain\" actions={[\n                    { label: 'Mark as read' }, { label: 'Archive' },\n                ]} />\n            </ComponentDemo>\n            <div className=\"mt-4\"><CodeBlock code={plainCode} language=\"tsx\" /></div>\n        </>\n    );\n};\n\nexport default Variants;\n"
        },
        {
          "title": "WithIcons",
          "code": "import React, { useState } from 'react';\nimport { ActionSheet, Button } from '../../../components';\nimport { CopyIcon, DownloadIcon, ShareIcon, TrashIcon } from '../../../assets/icons';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<ActionSheet\n    open={open}\n    onClose={close}\n    actions={[\n        { label: 'Share', icon: <ShareIcon /> },\n        { label: 'Copy link', icon: <CopyIcon /> },\n        { label: 'Download', icon: <DownloadIcon /> },\n        { label: 'Delete', icon: <TrashIcon />, destructive: true },\n    ]}\n/>`;\n\nconst WithIcons: React.FC = () => {\n    const [open, setOpen] = useState(false);\n    return (\n        <>\n            <ComponentDemo title=\"Actions with icons\" description=\"Pair each label with an icon — works for all variants.\">\n                <Button label=\"Open with icons\" variant=\"secondary\" onClick={() => setOpen(true)} />\n                <ActionSheet open={open} onClose={() => setOpen(false)} variant=\"material\" title=\"Photo\" actions={[\n                    { label: 'Share', icon: <ShareIcon /> },\n                    { label: 'Copy link', icon: <CopyIcon /> },\n                    { label: 'Download', icon: <DownloadIcon /> },\n                    { label: 'Delete', icon: <TrashIcon />, destructive: true },\n                ]} />\n            </ComponentDemo>\n            <div className=\"mt-4\"><CodeBlock code={code} language=\"tsx\" /></div>\n        </>\n    );\n};\n\nexport default WithIcons;\n"
        }
      ],
      "props": {
        "actionSheetProps": {
          "open": {
            "type": "boolean",
            "required": true,
            "description": "Whether the action sheet is visible."
          },
          "onClose": {
            "type": "() => void",
            "required": true,
            "description": "Called when the sheet should close (backdrop tap, Escape, cancel, or after a selection)."
          },
          "title": {
            "type": "ReactNode",
            "description": "Optional short title rendered at the top of the actions group."
          },
          "message": {
            "type": "ReactNode",
            "description": "Optional supporting message rendered under the title."
          },
          "actions": {
            "type": "ActionSheetAction[]",
            "required": true,
            "description": "Action items. Each item: { key?, label, description?, icon?, disabled?, destructive?, onSelect? }."
          },
          "cancelLabel": {
            "type": "string",
            "default": "'Cancel'",
            "description": "Label for the cancel button."
          },
          "showCancel": {
            "type": "boolean",
            "default": "true",
            "description": "Show the standalone cancel button below the actions group."
          },
          "onCancel": {
            "type": "() => void",
            "description": "Called when the cancel button is tapped, before onClose."
          },
          "variant": {
            "type": "'ios' | 'material' | 'plain'",
            "default": "'ios'",
            "description": "Visual variant. 'ios' centers items in a rounded card with a separate cancel pill; 'material' is a flush bottom sheet with left-aligned items; 'plain' merges actions and cancel into one card."
          },
          "closeOnSelect": {
            "type": "boolean",
            "default": "true",
            "description": "Auto-close after an action is selected."
          },
          "closeOnBackdropClick": {
            "type": "boolean",
            "default": "true",
            "description": "Close on backdrop tap."
          },
          "closeOnEscape": {
            "type": "boolean",
            "default": "true",
            "description": "Close when Escape is pressed."
          },
          "safeArea": {
            "type": "boolean",
            "default": "true",
            "description": "Apply env(safe-area-inset-bottom) so the sheet clears the iOS home indicator."
          },
          "className": {
            "type": "string",
            "description": "Additional CSS class for the sheet root."
          },
          "ariaLabel": {
            "type": "string",
            "description": "Accessible name for the dialog. Defaults to the title text if it's a string."
          }
        }
      },
      "storyDir": "action-sheet"
    },
    "ActivityGauge": {
      "name": "ActivityGauge",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React from 'react';\nimport { ActivityGauge } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { ActivityGauge } from 'fluxo-ui';\n\n<ActivityGauge\n  size=\"lg\"\n  centerTitle=\"ACTIVITY\"\n  centerValue=\"73%\"\n  centerSubLabel=\"of weekly goal\"\n  series={[\n    { name: 'Move', value: 320, max: 500, color: '#ef4444' },\n    { name: 'Exercise', value: 28, max: 30, color: '#22c55e' },\n    { name: 'Stand', value: 9, max: 12, color: '#3b82f6' },\n  ]}\n/>`;\n\nconst series = [\n    { name: 'Move', value: 320, max: 500, color: '#ef4444' },\n    { name: 'Exercise', value: 28, max: 30, color: '#22c55e' },\n    { name: 'Stand', value: 9, max: 12, color: '#3b82f6' },\n];\n\nconst BasicUsage: React.FC = () => (\n    <>\n        <ComponentDemo\n            title=\"Default Activity Gauge\"\n            description=\"A multi-series ring chart with a centered metric and a legend below.\"\n        >\n            <ActivityGauge\n                size=\"lg\"\n                centerTitle=\"ACTIVITY\"\n                centerValue=\"73%\"\n                centerSubLabel=\"of weekly goal\"\n                series={series}\n            />\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default BasicUsage;\n"
        },
        {
          "title": "Interactive",
          "code": "import React, { useState } from 'react';\nimport { ActivityGauge } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<ActivityGauge interactive series={series} onSeriesClick={(idx) => setSelected(idx)} />`;\n\nconst series = [\n    { name: 'Frontend', value: 88 },\n    { name: 'Backend', value: 64 },\n    { name: 'DB', value: 42 },\n    { name: 'Infra', value: 26 },\n];\n\nconst Interactive: React.FC = () => {\n    const [selected, setSelected] = useState<number | null>(null);\n    return (\n        <>\n            <ComponentDemo\n                title=\"Interactive Highlights\"\n                description=\"Hover or focus a ring or legend item to highlight that series. Click any item to handle a select event.\"\n            >\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 18, alignItems: 'center' }}>\n                    <ActivityGauge\n                        size=\"lg\"\n                        interactive\n                        series={series}\n                        centerTitle=\"UPTIME\"\n                        centerValue=\"55%\"\n                        onSeriesClick={(idx) => setSelected(idx)}\n                    />\n                    <div\n                        style={{\n                            padding: '12px 16px',\n                            background: 'var(--eui-bg-subtle)',\n                            border: '1px solid var(--eui-border-subtle)',\n                            borderRadius: 6,\n                            fontSize: 13,\n                            minWidth: 200,\n                            textAlign: 'center',\n                        }}\n                    >\n                        Selected:{' '}\n                        <strong>{selected != null ? series[selected].name : '—'}</strong>\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default Interactive;\n"
        },
        {
          "title": "Layouts",
          "code": "import React from 'react';\nimport { ActivityGauge } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst series = [\n    { name: 'Mobile', value: 78 },\n    { name: 'Desktop', value: 56 },\n    { name: 'Tablet', value: 32 },\n];\n\nconst code = `<ActivityGauge series={series} legend=\"bottom\" centerValue=\"55%\" />\n<ActivityGauge series={series} legend=\"right\" centerValue=\"55%\" />\n<ActivityGauge series={series} legend=\"none\" centerValue=\"55%\" />`;\n\nconst Layouts: React.FC = () => (\n    <>\n        <ComponentDemo\n            title=\"Legend Placement\"\n            description=\"Render the legend below, beside the gauge, or hide it entirely.\"\n        >\n            <div style={{ display: 'flex', gap: 32, flexWrap: 'wrap', alignItems: 'flex-start', justifyContent: 'center' }}>\n                <ActivityGauge size=\"md\" series={series} legend=\"bottom\" centerValue=\"55%\" />\n                <ActivityGauge size=\"md\" series={series} legend=\"right\" centerValue=\"55%\" />\n                <ActivityGauge size=\"md\" series={series} legend=\"none\" centerValue=\"55%\" />\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default Layouts;\n"
        },
        {
          "title": "Sizes",
          "code": "import React from 'react';\nimport { ActivityGauge } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst series = [\n    { name: 'Read', value: 70 },\n    { name: 'Watch', value: 45 },\n    { name: 'Write', value: 80 },\n];\n\nconst code = `<ActivityGauge size=\"sm\" series={series} centerValue=\"65%\" />\n<ActivityGauge size=\"md\" series={series} centerValue=\"65%\" />\n<ActivityGauge size=\"lg\" series={series} centerValue=\"65%\" />\n<ActivityGauge size=\"xl\" series={series} centerValue=\"65%\" />`;\n\nconst Sizes: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Sizes\" description=\"sm, md, lg, and xl preset sizes — or supply a custom number.\">\n            <div style={{ display: 'flex', gap: 24, flexWrap: 'wrap', alignItems: 'center', justifyContent: 'center' }}>\n                <ActivityGauge size=\"sm\" series={series} centerValue=\"65%\" legend=\"none\" />\n                <ActivityGauge size=\"md\" series={series} centerValue=\"65%\" legend=\"none\" />\n                <ActivityGauge size=\"lg\" series={series} centerValue=\"65%\" legend=\"none\" />\n                <ActivityGauge size=\"xl\" series={series} centerValue=\"65%\" legend=\"none\" />\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default Sizes;\n"
        }
      ],
      "props": {
        "activityGaugeProps": {
          "series": {
            "type": "Array<{ name: string; value: number; max?: number; color?: string }>",
            "required": true,
            "description": "Series rendered outermost to innermost as concentric rings"
          },
          "size": {
            "type": "'sm' | 'md' | 'lg' | 'xl' | number",
            "default": "'md'",
            "description": "Overall diameter (preset or pixel value)"
          },
          "ringThickness": {
            "type": "number",
            "description": "Width of each ring in px (auto-scaled with size when omitted)"
          },
          "ringGap": {
            "type": "number",
            "default": "6",
            "description": "Gap between rings in px"
          },
          "roundedCaps": {
            "type": "boolean",
            "default": "true",
            "description": "Round vs flat stroke caps"
          },
          "arcStart": {
            "type": "number",
            "default": "0",
            "description": "Start angle in degrees (applied to all rings)"
          },
          "arcEnd": {
            "type": "number",
            "default": "360",
            "description": "End angle in degrees (applied to all rings)"
          },
          "trackColor": {
            "type": "string",
            "default": "var(--eui-border-subtle)",
            "description": "Color of the unfilled portion of every ring"
          },
          "defaultColors": {
            "type": "string[]",
            "description": "Palette used when a series omits color"
          },
          "centerContent": {
            "type": "ReactNode",
            "description": "Custom slot for arbitrary center content"
          },
          "centerTitle": {
            "type": "string",
            "description": "Convenience title text shown in the center"
          },
          "centerValue": {
            "type": "string | number",
            "description": "Convenience big value shown in the center"
          },
          "centerSubLabel": {
            "type": "string",
            "description": "Convenience sub-label shown in the center"
          },
          "legend": {
            "type": "'bottom' | 'right' | 'none'",
            "default": "'bottom'",
            "description": "Legend placement"
          },
          "legendPosition": {
            "type": "'start' | 'center' | 'end'",
            "default": "'center'",
            "description": "Legend alignment along its axis"
          },
          "interactive": {
            "type": "boolean",
            "default": "false",
            "description": "Hover/focus highlights a series and dims the others"
          },
          "onSeriesClick": {
            "type": "(index: number) => void",
            "description": "Fired when a ring or legend item is activated"
          },
          "animate": {
            "type": "boolean",
            "default": "true",
            "description": "Sweep animation on mount; honors prefers-reduced-motion"
          },
          "tooltip": {
            "type": "boolean",
            "default": "true",
            "description": "Show tooltip with series details on hover/focus"
          },
          "valueFormatter": {
            "type": "(s: { name: string; value: number; max: number }) => string",
            "description": "Custom formatter for tooltip and ARIA description"
          },
          "id": {
            "type": "string",
            "description": "HTML id attribute"
          },
          "className": {
            "type": "string",
            "description": "Additional CSS classes"
          },
          "ariaLabel": {
            "type": "string",
            "description": "Accessible label override (defaults to series summary)"
          }
        }
      },
      "storyDir": "activity-gauge"
    },
    "AnimateOnView": {
      "name": "AnimateOnView",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "AllAnimations",
          "code": "import cn from 'classnames';\nimport React from 'react';\nimport { AnimateOnView } from '../../../components';\nimport type { AnimationType } from '../../../components';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\n\nconst animations: { type: AnimationType; label: string; color: string }[] = [\n    { type: 'fadeIn', label: 'Fade In', color: '#3b82f6' },\n    { type: 'fadeInUp', label: 'Fade In Up', color: '#8b5cf6' },\n    { type: 'fadeInDown', label: 'Fade In Down', color: '#06b6d4' },\n    { type: 'fadeInLeft', label: 'Fade In Left', color: '#10b981' },\n    { type: 'fadeInRight', label: 'Fade In Right', color: '#f59e0b' },\n    { type: 'zoomIn', label: 'Zoom In', color: '#ef4444' },\n    { type: 'zoomOut', label: 'Zoom Out', color: '#ec4899' },\n    { type: 'slideUp', label: 'Slide Up', color: '#14b8a6' },\n    { type: 'slideDown', label: 'Slide Down', color: '#6366f1' },\n    { type: 'slideLeft', label: 'Slide Left', color: '#f97316' },\n    { type: 'slideRight', label: 'Slide Right', color: '#84cc16' },\n    { type: 'flipX', label: 'Flip X', color: '#a855f7' },\n    { type: 'flipY', label: 'Flip Y', color: '#e11d48' },\n    { type: 'rotateIn', label: 'Rotate In', color: '#0ea5e9' },\n    { type: 'bounceIn', label: 'Bounce In', color: '#22c55e' },\n    { type: 'scaleUp', label: 'Scale Up', color: '#d946ef' },\n];\n\nconst AllAnimations: React.FC = () => {\n    const { isDark } = useStoryTheme();\n\n    return (\n        <ComponentDemo title=\"All Animation Types\" description=\"Scroll down to see each animation type in action. Each card animates independently.\">\n            <div className=\"grid sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4\">\n                {animations.map(({ type, label, color }, idx) => (\n                    <AnimateOnView\n                        key={type}\n                        animation={type}\n                        duration={700}\n                        delay={idx * 50}\n                        once={false}\n                    >\n                        <div\n                            className={cn('p-5 rounded-xl border text-center', {\n                                'border-white/10': isDark,\n                                'border-gray-200': !isDark,\n                            })}\n                            style={{ backgroundColor: `${color}15` }}\n                        >\n                            <div\n                                className=\"w-10 h-10 rounded-lg mx-auto mb-3 flex items-center justify-center\"\n                                style={{ backgroundColor: `${color}25`, color }}\n                            >\n                                <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" width=\"20\" height=\"20\">\n                                    <path d=\"M13 2L3 14h9l-1 8 10-12h-9l1-8z\" />\n                                </svg>\n                            </div>\n                            <p className=\"font-semibold text-sm\" style={{ color }}>{label}</p>\n                            <p className=\"text-xs mt-1\" style={{ color: 'var(--eui-text-muted)' }}>{type}</p>\n                        </div>\n                    </AnimateOnView>\n                ))}\n            </div>\n        </ComponentDemo>\n    );\n};\n\nexport default AllAnimations;\n"
        },
        {
          "title": "BasicUsage",
          "code": "import React from 'react';\nimport { AnimateOnView } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { AnimateOnView } from 'fluxo-ui';\n\n<AnimateOnView animation=\"fadeInUp\">\n  <div>This content animates when scrolled into view</div>\n</AnimateOnView>`;\n\nconst BasicUsage: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo title=\"Fade In Up\" description=\"Default animation triggers once when the element enters the viewport.\">\n                <div className=\"space-y-4\">\n                    <AnimateOnView animation=\"fadeInUp\">\n                        <div className=\"p-6 rounded-lg bg-[var(--eui-primary-subtle)] border border-[var(--eui-primary-border)] text-center\">\n                            <p className=\"text-lg font-semibold\" style={{ color: 'var(--eui-primary)' }}>\n                                Fade In Up\n                            </p>\n                            <p className=\"text-sm\" style={{ color: 'var(--eui-text-muted)' }}>\n                                Scroll down and back to see this animate\n                            </p>\n                        </div>\n                    </AnimateOnView>\n                    <AnimateOnView animation=\"fadeIn\" delay={200}>\n                        <div className=\"p-6 rounded-lg bg-[var(--eui-bg-subtle)] border border-[var(--eui-border)] text-center\">\n                            <p className=\"text-lg font-semibold\" style={{ color: 'var(--eui-text)' }}>\n                                Fade In\n                            </p>\n                            <p className=\"text-sm\" style={{ color: 'var(--eui-text-muted)' }}>\n                                With 200ms delay\n                            </p>\n                        </div>\n                    </AnimateOnView>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "ConfigOptions",
          "code": "import cn from 'classnames';\nimport React, { useState } from 'react';\nimport { AnimateOnView } from '../../../components';\nimport type { AnimationType } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\n\nconst code = `<AnimateOnView\n  animation=\"bounceIn\"\n  duration={1000}\n  delay={200}\n  easing=\"ease-out\"\n  once={false}\n  threshold={0.3}\n>\n  <div>Configurable animation</div>\n</AnimateOnView>`;\n\nconst animationOptions: AnimationType[] = [\n    'fadeIn', 'fadeInUp', 'fadeInDown', 'fadeInLeft', 'fadeInRight',\n    'zoomIn', 'zoomOut', 'slideUp', 'bounceIn', 'rotateIn',\n    'flipX', 'flipY', 'scaleUp',\n];\n\nconst ConfigOptions: React.FC = () => {\n    const { isDark } = useStoryTheme();\n    const [animation, setAnimation] = useState<AnimationType>('bounceIn');\n    const [duration, setDuration] = useState(600);\n    const [once, setOnce] = useState(false);\n    const [key, setKey] = useState(0);\n\n    const replay = () => setKey((k) => k + 1);\n\n    return (\n        <>\n            <ComponentDemo title=\"Configuration\" description=\"Customize animation type, duration, and behavior.\">\n                <div className=\"space-y-4\">\n                    <div className=\"flex flex-wrap gap-3 items-center\">\n                        <select\n                            value={animation}\n                            onChange={(e) => { setAnimation(e.target.value as AnimationType); replay(); }}\n                            className={cn('px-3 py-1.5 rounded-md border text-sm', {\n                                'bg-white/5 border-white/15 text-gray-200': isDark,\n                                'bg-white border-gray-300 text-gray-800': !isDark,\n                            })}\n                        >\n                            {animationOptions.map((a) => (\n                                <option key={a} value={a}>{a}</option>\n                            ))}\n                        </select>\n\n                        <label className=\"flex items-center gap-2 text-sm\" style={{ color: 'var(--eui-text-muted)' }}>\n                            Duration:\n                            <input\n                                type=\"range\"\n                                min={200}\n                                max={2000}\n                                step={100}\n                                value={duration}\n                                onChange={(e) => { setDuration(Number(e.target.value)); replay(); }}\n                            />\n                            <span className=\"font-mono text-xs\">{duration}ms</span>\n                        </label>\n\n                        <label className=\"flex items-center gap-2 text-sm\" style={{ color: 'var(--eui-text-muted)' }}>\n                            <input\n                                type=\"checkbox\"\n                                checked={once}\n                                onChange={(e) => setOnce(e.target.checked)}\n                            />\n                            Animate once\n                        </label>\n\n                        <button\n                            onClick={replay}\n                            className=\"px-3 py-1.5 rounded-md text-sm font-medium\"\n                            style={{ backgroundColor: 'var(--eui-primary)', color: 'var(--eui-text-on-primary)' }}\n                        >\n                            Replay\n                        </button>\n                    </div>\n\n                    <AnimateOnView\n                        key={key}\n                        animation={animation}\n                        duration={duration}\n                        once={once}\n                    >\n                        <div\n                            className={cn('p-8 rounded-xl border text-center', {\n                                'bg-white/3 border-white/10': isDark,\n                                'bg-white border-gray-200 shadow-md': !isDark,\n                            })}\n                        >\n                            <p className=\"text-xl font-bold\" style={{ color: 'var(--eui-primary)' }}>{animation}</p>\n                            <p className=\"text-sm mt-1\" style={{ color: 'var(--eui-text-muted)' }}>{duration}ms | {once ? 'once' : 'every time'}</p>\n                        </div>\n                    </AnimateOnView>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default ConfigOptions;\n"
        },
        {
          "title": "ScrollDemo",
          "code": "import cn from 'classnames';\nimport React from 'react';\nimport { AnimateOnView } from '../../../components';\nimport type { AnimationType } from '../../../components';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\n\nconst sections: { animation: AnimationType; title: string; content: string; accent: string }[] = [\n    { animation: 'fadeInLeft', title: 'Step 1: Design', content: 'Create beautiful interfaces with our component library. Every component is crafted with attention to detail and accessibility.', accent: '#3b82f6' },\n    { animation: 'fadeInRight', title: 'Step 2: Develop', content: 'Build with TypeScript-first components that provide full type safety and IntelliSense support out of the box.', accent: '#8b5cf6' },\n    { animation: 'fadeInLeft', title: 'Step 3: Test', content: 'Ensure quality with comprehensive accessibility support, keyboard navigation, and theme compatibility across all components.', accent: '#10b981' },\n    { animation: 'fadeInRight', title: 'Step 4: Deploy', content: 'Ship with confidence using tree-shakeable imports, CSS code splitting, and optimized bundle sizes.', accent: '#f59e0b' },\n    { animation: 'zoomIn', title: 'Step 5: Scale', content: 'Grow your application with our state management solution, 12 color themes, and mobile-responsive design system.', accent: '#ef4444' },\n    { animation: 'bounceIn', title: 'Step 6: Celebrate!', content: 'You have built something amazing. Time to share it with the world and keep iterating.', accent: '#ec4899' },\n];\n\nconst ScrollDemo: React.FC = () => {\n    const { isDark } = useStoryTheme();\n\n    return (\n        <ComponentDemo title=\"Scroll-triggered Showcase\" description=\"Scroll through this section to see alternating animations. Each section uses once={false} to re-animate on scroll.\">\n            <div className=\"space-y-6\">\n                {sections.map((section, idx) => (\n                    <AnimateOnView\n                        key={section.title}\n                        animation={section.animation}\n                        duration={800}\n                        delay={100}\n                        once={false}\n                    >\n                        <div\n                            className={cn('p-6 rounded-xl border flex gap-5 items-start', {\n                                'bg-white/3 border-white/10': isDark,\n                                'bg-white border-gray-200 shadow-sm': !isDark,\n                                'flex-row-reverse text-right': idx % 2 !== 0,\n                            })}\n                        >\n                            <div\n                                className=\"w-12 h-12 rounded-xl flex items-center justify-center text-white font-bold text-lg flex-shrink-0\"\n                                style={{ backgroundColor: section.accent }}\n                            >\n                                {idx + 1}\n                            </div>\n                            <div className=\"flex-1\">\n                                <h3 className=\"font-bold text-base mb-1\" style={{ color: section.accent }}>{section.title}</h3>\n                                <p className=\"text-sm leading-relaxed\" style={{ color: 'var(--eui-text-muted)' }}>{section.content}</p>\n                            </div>\n                        </div>\n                    </AnimateOnView>\n                ))}\n            </div>\n        </ComponentDemo>\n    );\n};\n\nexport default ScrollDemo;\n"
        },
        {
          "title": "StaggeredAnimations",
          "code": "import cn from 'classnames';\nimport React from 'react';\nimport { AnimateOnView } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\n\nconst code = `import { AnimateOnView } from 'fluxo-ui';\n\n{items.map((item, index) => (\n  <AnimateOnView\n    key={item.id}\n    animation=\"fadeInUp\"\n    stagger={100}\n    staggerIndex={index}\n  >\n    <Card {...item} />\n  </AnimateOnView>\n))}`;\n\nconst items = [\n    { title: 'Dashboard', desc: 'Overview of all metrics', icon: '📊' },\n    { title: 'Analytics', desc: 'Deep dive into data', icon: '📈' },\n    { title: 'Reports', desc: 'Generated insights', icon: '📋' },\n    { title: 'Settings', desc: 'Configure preferences', icon: '⚙️' },\n    { title: 'Users', desc: 'Manage team members', icon: '👥' },\n    { title: 'Billing', desc: 'Plans and payments', icon: '💳' },\n];\n\nconst StaggeredAnimations: React.FC = () => {\n    const { isDark } = useStoryTheme();\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Staggered Animation\"\n                description=\"Use stagger and staggerIndex to cascade animations across a list of elements.\"\n            >\n                <div className=\"grid sm:grid-cols-2 lg:grid-cols-3 gap-4\">\n                    {items.map((item, idx) => (\n                        <AnimateOnView key={item.title} animation=\"fadeInUp\" duration={500} stagger={100} staggerIndex={idx} once={false}>\n                            <div\n                                className={cn('p-4 rounded-lg border flex items-start gap-3', {\n                                    'bg-white/3 border-white/10': isDark,\n                                    'bg-white border-gray-200 shadow-sm': !isDark,\n                                })}\n                            >\n                                <span className=\"text-2xl\">{item.icon}</span>\n                                <div>\n                                    <p className={cn('font-semibold text-sm', { 'text-gray-200': isDark, 'text-gray-800': !isDark })}>\n                                        {item.title}\n                                    </p>\n                                    <p className=\"text-xs\" style={{ color: 'var(--eui-text-muted)' }}>\n                                        {item.desc}\n                                    </p>\n                                </div>\n                            </div>\n                        </AnimateOnView>\n                    ))}\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default StaggeredAnimations;\n"
        }
      ],
      "props": {
        "animateProps": {
          "animation": {
            "type": "'fadeIn' | 'fadeInUp' | 'fadeInDown' | 'fadeInLeft' | 'fadeInRight' | 'zoomIn' | 'zoomOut' | 'slideUp' | 'slideDown' | 'slideLeft' | 'slideRight' | 'flipX' | 'flipY' | 'rotateIn' | 'bounceIn' | 'scaleUp'",
            "default": "'fadeInUp'",
            "description": "The animation type to apply."
          },
          "duration": {
            "type": "number",
            "default": "600",
            "description": "Animation duration in milliseconds."
          },
          "delay": {
            "type": "number",
            "default": "0",
            "description": "Delay before animation starts in milliseconds."
          },
          "easing": {
            "type": "'ease' | 'ease-in' | 'ease-out' | 'ease-in-out' | 'linear'",
            "default": "'ease-out'",
            "description": "CSS animation timing function."
          },
          "once": {
            "type": "boolean",
            "default": "true",
            "description": "If true, animate only the first time the element enters the viewport."
          },
          "threshold": {
            "type": "number",
            "default": "0.1",
            "description": "IntersectionObserver threshold (0-1). How much of the element must be visible."
          },
          "rootMargin": {
            "type": "string",
            "default": "'0px'",
            "description": "IntersectionObserver root margin."
          },
          "as": {
            "type": "React.ElementType",
            "default": "'div'",
            "description": "The HTML element or component to render as."
          },
          "disabled": {
            "type": "boolean",
            "default": "false",
            "description": "Skip animation and show content immediately."
          },
          "onVisible": {
            "type": "() => void",
            "description": "Called when the element becomes visible."
          },
          "onHidden": {
            "type": "() => void",
            "description": "Called when the element leaves the viewport (if once=false)."
          },
          "stagger": {
            "type": "number",
            "default": "0",
            "description": "Delay increment per item in milliseconds for staggered lists."
          },
          "staggerIndex": {
            "type": "number",
            "default": "0",
            "description": "Index of this item in a staggered sequence."
          },
          "children": {
            "type": "ReactNode",
            "required": true,
            "description": "Content to animate."
          },
          "className": {
            "type": "string",
            "description": "Additional CSS class."
          }
        }
      },
      "storyDir": "animate-on-view"
    },
    "Avatar": {
      "name": "Avatar",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React from 'react';\nimport { Avatar } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { Avatar } from 'fluxo-ui';\n\n<Avatar src=\"https://i.pravatar.cc/120?u=jane\" alt=\"Jane Doe\" />\n<Avatar name=\"Jane Doe\" />\n<Avatar name=\"Marcus\" status=\"online\" />\n<Avatar name=\"Anna\" status=\"busy\" shape=\"rounded\" />`;\n\nconst BasicUsage: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Default Avatar\" description=\"Image, initials, and icon fallbacks with optional status dot.\">\n            <div style={{ display: 'flex', gap: 16, flexWrap: 'wrap', alignItems: 'center', justifyContent: 'center' }}>\n                <Avatar src=\"https://i.pravatar.cc/120?u=jane\" alt=\"Jane Doe\" />\n                <Avatar name=\"Jane Doe\" />\n                <Avatar name=\"Marcus Lopez\" status=\"online\" />\n                <Avatar name=\"Anna Kim\" status=\"busy\" shape=\"rounded\" />\n                <Avatar name=\"Olivia Park\" status=\"away\" shape=\"square\" />\n                <Avatar />\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default BasicUsage;\n"
        },
        {
          "title": "Clickable",
          "code": "import React, { useState } from 'react';\nimport { Avatar } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<Avatar name=\"Jane\" onClick={() => setSelected('Jane')} />`;\n\nconst people = ['Jane Doe', 'Marcus Lopez', 'Anna Kim', 'Olivia Park'];\n\nconst Clickable: React.FC = () => {\n    const [selected, setSelected] = useState<string | null>(null);\n    return (\n        <>\n            <ComponentDemo title=\"Clickable Avatar\" description=\"When onClick is provided the avatar renders as a focusable button.\">\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16, alignItems: 'center' }}>\n                    <div style={{ display: 'flex', gap: 12, flexWrap: 'wrap', justifyContent: 'center' }}>\n                        {people.map((p) => (\n                            <Avatar key={p} name={p} onClick={() => setSelected(p)} status=\"online\" />\n                        ))}\n                    </div>\n                    <div\n                        style={{\n                            padding: '10px 14px',\n                            background: 'var(--eui-bg-subtle)',\n                            border: '1px solid var(--eui-border-subtle)',\n                            borderRadius: 6,\n                            fontSize: 13,\n                            minWidth: 240,\n                            textAlign: 'center',\n                        }}\n                    >\n                        Selected: <strong>{selected ?? '—'}</strong>\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default Clickable;\n"
        },
        {
          "title": "Group",
          "code": "import React, { useState } from 'react';\nimport { Avatar, AvatarGroup } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `const [selected, setSelected] = useState(null);\n\n<AvatarGroup\n  max={4}\n  onAvatarClick={(item, index) => setSelected({ ...item, index })}\n>\n  <Avatar name=\"Jane Doe\" status=\"online\" />\n  <Avatar name=\"Marcus Lopez\" status=\"busy\" />\n  <Avatar name=\"Anna Kim\" status=\"away\" />\n  <Avatar name=\"Olivia Park\" status=\"offline\" />\n  <Avatar name=\"Diego Reyes\" />\n  <Avatar name=\"Hugo Liu\" />\n</AvatarGroup>`;\n\nconst peopleItems = [\n    { name: 'Jane Doe', status: 'online' as const },\n    { name: 'Marcus Lopez', status: 'busy' as const },\n    { name: 'Anna Kim', status: 'away' as const },\n    { name: 'Olivia Park', status: 'offline' as const },\n    { name: 'Diego Reyes' },\n    { name: 'Hugo Liu' },\n    { name: 'Sara Toth' },\n];\n\ninterface SelectedAvatar {\n    name?: string;\n    status?: string;\n    index: number;\n}\n\nconst Group: React.FC = () => {\n    const [selected, setSelected] = useState<SelectedAvatar | null>(null);\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Avatar Group\"\n                description=\"Stack avatars with overflow and an optional popover listing the hidden ones (click +N). Hover any avatar to bring it to the front, click to fire the per-avatar callback.\"\n            >\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16, alignItems: 'center' }}>\n                    <AvatarGroup\n                        max={4}\n                        ariaLabel=\"Project members\"\n                        onAvatarClick={(item, index) => setSelected({ name: item.name, status: item.status, index })}\n                    >\n                        {peopleItems.map((p) => (\n                            <Avatar key={p.name} name={p.name} status={p.status} />\n                        ))}\n                    </AvatarGroup>\n\n                    <div\n                        style={{\n                            padding: '10px 14px',\n                            background: 'var(--eui-bg-subtle)',\n                            border: '1px solid var(--eui-border-subtle)',\n                            borderRadius: 6,\n                            color: 'var(--eui-text)',\n                            minWidth: 260,\n                            textAlign: 'center',\n                            fontSize: 13,\n                        }}\n                    >\n                        {selected\n                            ? (\n                                <>\n                                    Selected: <strong>{selected.name}</strong>\n                                    {selected.status && <> &middot; {selected.status}</>}\n                                    {' '}(index {selected.index})\n                                </>\n                            )\n                            : 'Click an avatar (or one inside the +N popover) to see the callback fire.'}\n                    </div>\n\n                    <AvatarGroup max={3} shape=\"rounded\" overlap={12}>\n                        <Avatar name=\"Jane Doe\" status=\"online\" />\n                        <Avatar name=\"Marcus Lopez\" status=\"busy\" />\n                        <Avatar name=\"Anna Kim\" status=\"away\" />\n                        <Avatar name=\"Olivia Park\" status=\"offline\" />\n                        <Avatar name=\"Diego Reyes\" />\n                    </AvatarGroup>\n\n                    <AvatarGroup direction=\"rtl\" max={5} size=\"sm\">\n                        {peopleItems.map((p) => (\n                            <Avatar key={p.name} name={p.name} />\n                        ))}\n                    </AvatarGroup>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default Group;\n"
        },
        {
          "title": "Sizes",
          "code": "import React from 'react';\nimport { Avatar } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<Avatar name=\"A\" size=\"xs\" />\n<Avatar name=\"A\" size=\"sm\" />\n<Avatar name=\"A\" size=\"md\" />\n<Avatar name=\"A\" size=\"lg\" />\n<Avatar name=\"A\" size=\"xl\" />\n<Avatar name=\"A\" size={120} />`;\n\nconst Sizes: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Sizes\" description=\"Five preset sizes plus arbitrary pixel values.\">\n            <div style={{ display: 'flex', gap: 16, flexWrap: 'wrap', alignItems: 'center', justifyContent: 'center' }}>\n                {(['xs', 'sm', 'md', 'lg', 'xl'] as const).map((s) => (\n                    <div key={s} style={{ display: 'flex', flexDirection: 'column', gap: 4, alignItems: 'center' }}>\n                        <Avatar name=\"Jane Doe\" size={s} status=\"online\" />\n                        <span style={{ fontSize: 11, color: 'var(--eui-text-muted)' }}>{s}</span>\n                    </div>\n                ))}\n                <div style={{ display: 'flex', flexDirection: 'column', gap: 4, alignItems: 'center' }}>\n                    <Avatar name=\"Jane Doe\" size={120} status=\"online\" />\n                    <span style={{ fontSize: 11, color: 'var(--eui-text-muted)' }}>120px</span>\n                </div>\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default Sizes;\n"
        },
        {
          "title": "Statuses",
          "code": "import React from 'react';\nimport { Avatar, AvatarStatus, AvatarStatusPosition } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<Avatar name=\"A\" status=\"online\" />\n<Avatar name=\"B\" status=\"busy\" statusPosition=\"top-right\" />\n<Avatar name=\"C\" status=\"away\" statusPosition=\"bottom-left\" />\n<Avatar name=\"D\" status=\"offline\" statusPosition=\"top-left\" />`;\n\nconst positions: AvatarStatusPosition[] = ['top-left', 'top-right', 'bottom-left', 'bottom-right'];\nconst statuses: AvatarStatus[] = ['online', 'offline', 'busy', 'away'];\n\nconst Statuses: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Statuses & Positions\" description=\"All four statuses across all four positions.\">\n            <div style={{ display: 'grid', gridTemplateColumns: 'auto repeat(4, 1fr)', gap: 12, alignItems: 'center' }}>\n                <span></span>\n                {statuses.map((s) => (\n                    <span key={s} style={{ fontSize: 11, color: 'var(--eui-text-muted)', textAlign: 'center' }}>\n                        {s}\n                    </span>\n                ))}\n                {positions.map((pos) => (\n                    <React.Fragment key={pos}>\n                        <span style={{ fontSize: 11, color: 'var(--eui-text-muted)' }}>{pos}</span>\n                        {statuses.map((status) => (\n                            <div key={`${pos}-${status}`} style={{ display: 'flex', justifyContent: 'center' }}>\n                                <Avatar size=\"lg\" name=\"J D\" status={status} statusPosition={pos} />\n                            </div>\n                        ))}\n                    </React.Fragment>\n                ))}\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default Statuses;\n"
        }
      ],
      "props": {
        "avatarProps": {
          "src": {
            "type": "string",
            "description": "Image URL"
          },
          "name": {
            "type": "string",
            "description": "Used to derive initials and a deterministic background color when no src is provided or when the image fails"
          },
          "icon": {
            "type": "IconComponent | ReactElement",
            "description": "Fallback when neither src nor name is available"
          },
          "alt": {
            "type": "string",
            "description": "Accessible image alt text (defaults to name)"
          },
          "shape": {
            "type": "'circle' | 'rounded' | 'square'",
            "default": "'circle'",
            "description": "Avatar shape"
          },
          "size": {
            "type": "'xs' | 'sm' | 'md' | 'lg' | 'xl' | number",
            "default": "'md'",
            "description": "Preset size or pixel value"
          },
          "status": {
            "type": "'online' | 'offline' | 'busy' | 'away'",
            "description": "Status indicator dot"
          },
          "statusPosition": {
            "type": "'top-right' | 'top-left' | 'bottom-right' | 'bottom-left'",
            "default": "'bottom-right'",
            "description": "Status dot placement"
          },
          "colorFromName": {
            "type": "boolean",
            "default": "true",
            "description": "When no src, derive a stable background color from the name"
          },
          "loading": {
            "type": "'lazy' | 'eager'",
            "default": "'lazy'",
            "description": "Image loading strategy"
          },
          "onClick": {
            "type": "(e: MouseEvent) => void",
            "description": "When provided, renders as a focusable button"
          },
          "id": {
            "type": "string",
            "description": "HTML id attribute"
          },
          "className": {
            "type": "string",
            "description": "Additional CSS classes"
          },
          "ariaLabel": {
            "type": "string",
            "description": "Accessible label override"
          }
        },
        "avatarGroupProps": {
          "children": {
            "type": "ReactNode",
            "description": "Multiple Avatar children"
          },
          "items": {
            "type": "Array<AvatarProps>",
            "description": "Alternative array prop instead of children"
          },
          "max": {
            "type": "number",
            "description": "Cap visible avatars; the rest collapse into a +N chip"
          },
          "overlap": {
            "type": "number",
            "default": "8",
            "description": "Pixels of overlap between adjacent avatars"
          },
          "direction": {
            "type": "'ltr' | 'rtl'",
            "default": "'ltr'",
            "description": "Visual stack order"
          },
          "size": {
            "type": "'xs' | 'sm' | 'md' | 'lg' | 'xl' | number",
            "default": "'md'",
            "description": "Applied to all children"
          },
          "shape": {
            "type": "'circle' | 'rounded' | 'square'",
            "default": "'circle'",
            "description": "Applied to all children"
          },
          "onAvatarClick": {
            "type": "(item: AvatarProps, index: number, e: MouseEvent) => void",
            "description": "Fires when any avatar inside the group is clicked, including avatars revealed via the overflow popover. The index reflects the avatar's position in the original full list."
          },
          "onOverflowClick": {
            "type": "() => void",
            "description": "Custom handler for the +N chip; when omitted, opens a popover with the hidden avatars"
          },
          "id": {
            "type": "string",
            "description": "HTML id attribute"
          },
          "className": {
            "type": "string",
            "description": "Additional CSS classes"
          },
          "ariaLabel": {
            "type": "string",
            "description": "Accessible label for the group"
          }
        }
      },
      "storyDir": "avatar"
    },
    "Barcode": {
      "name": "Barcode",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React, { useState } from 'react';\nimport { Barcode, BarcodeFormat } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst formatExamples: Record<BarcodeFormat, string> = {\n    CODE128: 'FLUXO-UI-2026',\n    CODE39: 'FLUXO UI',\n    EAN13: '4006381333931',\n    EAN8: '12345670',\n    UPC: '036000291452',\n    ITF: '12345678',\n};\n\nconst code = `<Barcode value=\"FLUXO-UI-2026\" format=\"CODE128\" />`;\n\nconst BasicUsage: React.FC = () => {\n    const [format, setFormat] = useState<BarcodeFormat>('CODE128');\n    const [value, setValue] = useState(formatExamples.CODE128);\n    const [error, setError] = useState<string | null>(null);\n\n    const handleFormatChange = (next: BarcodeFormat) => {\n        setFormat(next);\n        setValue(formatExamples[next]);\n        setError(null);\n    };\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Default Barcode\"\n                description=\"Pick a format, type your value, and scan with a barcode reader app on your phone to verify. Invalid inputs render an inline error.\"\n            >\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16, alignItems: 'center' }}>\n                    <Barcode\n                        value={value}\n                        format={format}\n                        width={3}\n                        height={110}\n                        fontSize={16}\n                        onError={(err) => setError(err.message)}\n                    />\n                    <div\n                        style={{\n                            display: 'grid',\n                            gridTemplateColumns: 'auto 1fr',\n                            gap: 12,\n                            alignItems: 'center',\n                            padding: '12px 16px',\n                            background: 'var(--eui-bg-subtle)',\n                            border: '1px solid var(--eui-border-subtle)',\n                            borderRadius: 6,\n                            width: '100%',\n                            maxWidth: 520,\n                            fontSize: 13,\n                        }}\n                    >\n                        <label htmlFor=\"bc-fmt\">Format</label>\n                        <select\n                            id=\"bc-fmt\"\n                            value={format}\n                            onChange={(e) => handleFormatChange(e.target.value as BarcodeFormat)}\n                            style={{ padding: '4px 8px', borderRadius: 4 }}\n                        >\n                            {(Object.keys(formatExamples) as BarcodeFormat[]).map((f) => (\n                                <option key={f} value={f}>\n                                    {f}\n                                </option>\n                            ))}\n                        </select>\n\n                        <label htmlFor=\"bc-val\">Value</label>\n                        <input\n                            id=\"bc-val\"\n                            type=\"text\"\n                            value={value}\n                            onChange={(e) => {\n                                setValue(e.target.value);\n                                setError(null);\n                            }}\n                            style={{\n                                padding: '4px 8px',\n                                borderRadius: 4,\n                                border: '1px solid var(--eui-border)',\n                                background: 'var(--eui-bg)',\n                                color: 'var(--eui-text)',\n                            }}\n                        />\n\n                        {error && (\n                            <span style={{ gridColumn: '1 / -1', color: '#ef4444', fontSize: 12 }}>\n                                {error}\n                            </span>\n                        )}\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "Customization",
          "code": "import React, { useState } from 'react';\nimport { Barcode } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<Barcode\n  value=\"HELLO\"\n  format=\"CODE39\"\n  width={3}\n  height={100}\n  foreground=\"#3b82f6\"\n  background=\"var(--eui-bg)\"\n  fontSize={16}\n  displayValue\n/>`;\n\nconst Customization: React.FC = () => {\n    const [width, setWidth] = useState(2);\n    const [height, setHeight] = useState(80);\n    const [foreground, setForeground] = useState('#1f2937');\n    const [displayValue, setDisplayValue] = useState(true);\n    const [margin, setMargin] = useState(10);\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Visual Customization\"\n                description=\"Tune bar width, height, color, margin, and the human-readable text below.\"\n            >\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16, alignItems: 'center' }}>\n                    <Barcode\n                        value=\"HELLO\"\n                        format=\"CODE39\"\n                        width={width}\n                        height={height}\n                        foreground={foreground}\n                        margin={margin}\n                        displayValue={displayValue}\n                    />\n                    <div\n                        style={{\n                            display: 'grid',\n                            gridTemplateColumns: 'auto 1fr auto',\n                            gap: 12,\n                            alignItems: 'center',\n                            padding: '12px 16px',\n                            background: 'var(--eui-bg-subtle)',\n                            border: '1px solid var(--eui-border-subtle)',\n                            borderRadius: 6,\n                            width: '100%',\n                            maxWidth: 520,\n                            fontSize: 13,\n                        }}\n                    >\n                        <label htmlFor=\"bc-width\">Bar width</label>\n                        <input id=\"bc-width\" type=\"range\" min={1} max={6} value={width} onChange={(e) => setWidth(Number(e.target.value))} />\n                        <span>{width}px</span>\n\n                        <label htmlFor=\"bc-height\">Height</label>\n                        <input\n                            id=\"bc-height\"\n                            type=\"range\"\n                            min={40}\n                            max={200}\n                            step={4}\n                            value={height}\n                            onChange={(e) => setHeight(Number(e.target.value))}\n                        />\n                        <span>{height}px</span>\n\n                        <label htmlFor=\"bc-margin\">Margin</label>\n                        <input\n                            id=\"bc-margin\"\n                            type=\"range\"\n                            min={0}\n                            max={30}\n                            step={1}\n                            value={margin}\n                            onChange={(e) => setMargin(Number(e.target.value))}\n                        />\n                        <span>{margin}px</span>\n\n                        <label htmlFor=\"bc-fg\">Foreground</label>\n                        <input id=\"bc-fg\" type=\"color\" value={foreground} onChange={(e) => setForeground(e.target.value)} />\n                        <span>{foreground}</span>\n\n                        <label htmlFor=\"bc-display\">Show text</label>\n                        <input\n                            id=\"bc-display\"\n                            type=\"checkbox\"\n                            checked={displayValue}\n                            onChange={(e) => setDisplayValue(e.target.checked)}\n                        />\n                        <span>{displayValue ? 'on' : 'off'}</span>\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default Customization;\n"
        },
        {
          "title": "Formats",
          "code": "import React from 'react';\nimport { Barcode } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst formats: { format: 'CODE128' | 'CODE39' | 'EAN13' | 'EAN8' | 'UPC' | 'ITF'; value: string; note: string }[] = [\n    { format: 'CODE128', value: 'FLUXO-UI-2026', note: 'Most flexible — alphanumeric + symbols' },\n    { format: 'CODE39', value: 'FLUXO UI', note: '43-char uppercase alphabet' },\n    { format: 'EAN13', value: '4006381333931', note: '12 or 13 digits, retail' },\n    { format: 'EAN8', value: '12345670', note: '7 or 8 digits, small packages' },\n    { format: 'UPC', value: '036000291452', note: '11 or 12 digits, US retail' },\n    { format: 'ITF', value: '12345678', note: 'Even-length digits, logistics' },\n];\n\nconst code = `<Barcode format=\"CODE128\" value=\"FLUXO-UI-2026\" />\n<Barcode format=\"EAN13\" value=\"4006381333931\" />`;\n\nconst Formats: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Supported Formats\" description=\"Six 1D symbologies cover almost every use case.\">\n            <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(260px, 1fr))', gap: 24, width: '100%' }}>\n                {formats.map(({ format, value, note }) => (\n                    <div\n                        key={format}\n                        style={{\n                            display: 'flex',\n                            flexDirection: 'column',\n                            gap: 8,\n                            padding: 12,\n                            border: '1px solid var(--eui-border-subtle)',\n                            borderRadius: 6,\n                        }}\n                    >\n                        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>\n                            <strong style={{ fontSize: 13 }}>{format}</strong>\n                            <span style={{ fontSize: 11, color: 'var(--eui-text-muted)' }}>{note}</span>\n                        </div>\n                        <Barcode value={value} format={format} height={60} fontSize={12} />\n                    </div>\n                ))}\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default Formats;\n"
        }
      ],
      "props": {
        "barcodeProps": {
          "value": {
            "type": "string",
            "required": true,
            "description": "Value to encode (numeric for EAN/UPC/ITF, alphanumeric for CODE39/CODE128)"
          },
          "format": {
            "type": "'CODE128' | 'CODE39' | 'EAN13' | 'EAN8' | 'UPC' | 'ITF'",
            "required": true,
            "description": "Barcode symbology"
          },
          "width": {
            "type": "number",
            "default": "2",
            "description": "Width of the narrowest bar in px"
          },
          "height": {
            "type": "number",
            "default": "80",
            "description": "Bar height in px"
          },
          "displayValue": {
            "type": "boolean",
            "default": "true",
            "description": "Show the human-readable text below the bars"
          },
          "font": {
            "type": "string",
            "default": "'inherit'",
            "description": "Font family for the human-readable text"
          },
          "fontSize": {
            "type": "number",
            "default": "14",
            "description": "Font size for the human-readable text"
          },
          "textMargin": {
            "type": "number",
            "default": "6",
            "description": "Vertical gap between bars and text"
          },
          "foreground": {
            "type": "string",
            "default": "'#000000'",
            "description": "Bar and text color. Default is black for maximum scannability — CSS variables that flip with dark mode are NOT recommended (most barcode scanners reject light-on-dark)"
          },
          "background": {
            "type": "string",
            "default": "'#ffffff'",
            "description": "Background color. Default is white for maximum scannability. Use 'transparent' to omit"
          },
          "margin": {
            "type": "number",
            "default": "10",
            "description": "Quiet zone in px on each side"
          },
          "onError": {
            "type": "(err: Error) => void",
            "description": "Fired when input is invalid for the chosen format"
          },
          "id": {
            "type": "string",
            "description": "HTML id attribute"
          },
          "className": {
            "type": "string",
            "description": "Additional CSS classes"
          },
          "alt": {
            "type": "string",
            "description": "Accessible label override"
          }
        }
      },
      "storyDir": "barcode"
    },
    "Calendar": {
      "name": "Calendar",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React from 'react';\nimport { Calendar, ViewMode } from '../../../components/calendar';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { CodeBlock } from '../../CodeBlock';\nimport { sampleEntries, basicCalendarCode } from './calendar-story-data';\n\nconst BasicUsage: React.FC = () => {\n  return (\n    <>\n      <ComponentDemo title=\"Basic Calendar\" description=\"A fully interactive calendar with default configuration.\" centered={false}>\n        <div style={{ height: 600, width: '100%' }}>\n          <Calendar\n            entries={sampleEntries}\n            initialView={ViewMode.timeGridWeek}\n            height=\"100%\"\n            editable\n            selectable\n            nowIndicator\n            showNavigationPicker\n            onEntryClick={(entry) => alert(`Clicked: ${entry.title}`)}\n            onDateSelect={(info) => alert(`Selected: ${info.start.toLocaleTimeString()} - ${info.end.toLocaleTimeString()}`)}\n          />\n        </div>\n      </ComponentDemo>\n      <div className=\"mt-4\">\n        <CodeBlock title=\"Basic Usage\" code={basicCalendarCode} />\n      </div>\n    </>\n  );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "CompactMode",
          "code": "import React from 'react';\nimport { Calendar, ViewMode } from '../../../components/calendar';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { sampleEntries } from './calendar-story-data';\n\nconst CompactMode: React.FC = () => {\n  return (\n    <ComponentDemo title=\"Compact & Embedded Mode\" description=\"Use compact mode for embedding in sidebars or dashboards. Hide toolbar sections as needed.\" centered={false}>\n      <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\" style={{ width: '100%' }}>\n        <div>\n          <h4 className=\"text-sm font-semibold mb-2\">Compact Mode</h4>\n          <div style={{ height: 350, width: '100%' }}>\n            <Calendar\n              entries={sampleEntries}\n              initialView={ViewMode.dayGridMonth}\n              height=\"100%\"\n              compact\n              nowIndicator={false}\n            />\n          </div>\n        </div>\n        <div>\n          <h4 className=\"text-sm font-semibold mb-2\">Hidden Toolbar Sections</h4>\n          <div style={{ height: 350, width: '100%' }}>\n            <Calendar\n              entries={sampleEntries}\n              initialView={ViewMode.listWeek}\n              height=\"100%\"\n              hideToolbarViewSwitcher\n              hideToolbarNavigation={false}\n            />\n          </div>\n        </div>\n      </div>\n    </ComponentDemo>\n  );\n};\n\nexport default CompactMode;\n"
        },
        {
          "title": "CustomRendering",
          "code": "import React from 'react';\nimport { Calendar, ViewMode } from '../../../components/calendar';\nimport type { ResolvedCalendarEntry, EntryRenderContext } from '../../../components/calendar';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { CodeBlock } from '../../CodeBlock';\nimport { sampleEntries, customRenderCode } from './calendar-story-data';\n\nconst typeIcons: Record<string, string> = {\n  meeting: '\\uD83D\\uDCE5',\n  task: '\\u2705',\n  personal: '\\uD83C\\uDFE0',\n  event: '\\uD83C\\uDF89',\n  deadline: '\\u26A0\\uFE0F',\n};\n\nfunction renderCustomEntry(entry: ResolvedCalendarEntry, context: EntryRenderContext) {\n  const icon = typeIcons[String(entry.entryType)] ?? '\\uD83D\\uDCC5';\n  return (\n    <div style={{ padding: '1px 2px', display: 'flex', alignItems: 'center', gap: 4, minWidth: 0 }}>\n      <span style={{ fontSize: context.isCompact ? '0.65rem' : '0.75rem', flexShrink: 0 }}>{icon}</span>\n      <span style={{\n        fontWeight: 600,\n        fontSize: context.isCompact ? '0.65rem' : '0.75rem',\n        overflow: 'hidden',\n        textOverflow: 'ellipsis',\n        whiteSpace: 'nowrap',\n      }}>\n        {entry.title}\n      </span>\n    </div>\n  );\n}\n\nconst CustomRendering: React.FC = () => {\n  return (\n    <>\n      <ComponentDemo title=\"Custom Entry Rendering\" description=\"Use renderEntry to fully control entry appearance with icons and custom layouts.\" centered={false}>\n        <div style={{ height: 550, width: '100%' }}>\n          <Calendar\n            entries={sampleEntries}\n            initialView={ViewMode.timeGridWeek}\n            height=\"100%\"\n            renderEntry={renderCustomEntry}\n            nowIndicator\n          />\n        </div>\n      </ComponentDemo>\n      <div className=\"mt-4\">\n        <CodeBlock title=\"Custom Render\" code={customRenderCode} />\n      </div>\n    </>\n  );\n};\n\nexport default CustomRendering;\n"
        },
        {
          "title": "CustomToolbarEnd",
          "code": "import React from 'react';\nimport { Button } from '../../../components/Button';\nimport type { ToolbarEndRenderProps } from '../../../components/calendar';\nimport { Calendar, ViewMode } from '../../../components/calendar';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { sampleEntries } from './calendar-story-data';\n\nconst customToolbarEndCode = `import { Calendar, ToolbarEndRenderProps } from 'fluxo-ui';\n\n<Calendar\n  entries={entries}\n  initialView=\"timeGridWeek\"\n  showNavigationPicker\n  renderToolbarEnd={({ viewSwitcher, pluginActions }) => (\n    <div style={{ display: 'flex', alignItems: 'center', gap: '0.5rem' }}>\n      <button onClick={() => alert('Custom action!')}>+ New Event</button>\n      {pluginActions}\n      {viewSwitcher}\n    </div>\n  )}\n/>\n\n// The renderToolbarEnd callback receives:\n// - viewSwitcher: The view mode dropdown (ReactNode)\n// - pluginActions: Plugin toolbar actions for the end slot (ReactNode)\n// Compose them in any order alongside your own components.`;\n\nconst iconOnlyPickerCode = `<Calendar\n  entries={entries}\n  initialView=\"timeGridWeek\"\n  showNavigationPicker\n  navigationPickerIconOnly\n/>\n\n// With navigationPickerIconOnly:\n// - Title text remains visible as the header\n// - A small calendar icon appears next to nav buttons\n//   to open the date picker popover\n// Without navigationPickerIconOnly (default):\n// - The date range picker replaces the title,\n//   styled as the header text with a picker icon`;\n\nconst CustomToolbarEnd: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo\n                title=\"Custom Toolbar End\"\n                description=\"Use renderToolbarEnd to compose the right side of the toolbar with your own components alongside the built-in view switcher and plugin actions.\"\n                centered={false}\n            >\n                <div style={{ height: 500, width: '100%' }}>\n                    <Calendar\n                        entries={sampleEntries}\n                        initialView={ViewMode.timeGridWeek}\n                        height=\"100%\"\n                        showNavigationPicker\n                        nowIndicator\n                        renderToolbarEnd={({ viewSwitcher, pluginActions }: ToolbarEndRenderProps) => (\n                            <div style={{ display: 'flex', alignItems: 'center', gap: '0.5rem' }}>\n                                <Button label=\"+ New Event\" size=\"sm\" onClick={() => alert('Create new event!')} />\n                                <Button label=\"Filter\" size=\"sm\" layout=\"outlined\" onClick={() => alert('Open filters!')} />\n                                {pluginActions}\n                                {viewSwitcher}\n                            </div>\n                        )}\n                    />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock title=\"Custom Toolbar End\" code={customToolbarEndCode} />\n            </div>\n\n            <div className=\"mt-8\">\n                <ComponentDemo\n                    title=\"Icon-Only Navigation Picker\"\n                    description=\"With navigationPickerIconOnly, the title remains visible as the header while a compact calendar icon provides quick date navigation.\"\n                    centered={false}\n                >\n                    <div style={{ height: 500, width: '100%' }}>\n                        <Calendar\n                            entries={sampleEntries}\n                            initialView={ViewMode.timeGridWeek}\n                            height=\"100%\"\n                            showNavigationPicker\n                            navigationPickerIconOnly\n                            nowIndicator\n                        />\n                    </div>\n                </ComponentDemo>\n                <div className=\"mt-4\">\n                    <CodeBlock title=\"Icon-Only Navigation Picker\" code={iconOnlyPickerCode} />\n                </div>\n            </div>\n        </>\n    );\n};\n\nexport default CustomToolbarEnd;\n"
        },
        {
          "title": "DateBackgrounds",
          "code": "import React from 'react';\nimport { Calendar, ViewMode } from '../../../components/calendar';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { CodeBlock } from '../../CodeBlock';\nimport { sampleEntries, sampleDateBackgrounds, sampleDateRangeBackgrounds, dateBackgroundCode } from './calendar-story-data';\n\nconst DateBackgrounds: React.FC = () => {\n  return (\n    <>\n      <ComponentDemo title=\"Date Backgrounds\" description=\"Highlight specific dates or date ranges with custom background colors. Works across all views.\" centered={false}>\n        <div style={{ height: 550, width: '100%' }}>\n          <Calendar\n            entries={sampleEntries}\n            initialView={ViewMode.timeGridWeek}\n            height=\"100%\"\n            nowIndicator\n            dateBackgrounds={sampleDateBackgrounds}\n            dateRangeBackgrounds={sampleDateRangeBackgrounds}\n          />\n        </div>\n      </ComponentDemo>\n      <div className=\"mt-4\">\n        <CodeBlock title=\"Date Backgrounds\" code={dateBackgroundCode} />\n      </div>\n    </>\n  );\n};\n\nexport default DateBackgrounds;\n"
        },
        {
          "title": "DragDropResize",
          "code": "import React, { useState } from 'react';\nimport { Calendar, ViewMode } from '../../../components/calendar';\nimport type { CalendarEntry } from '../../../components/calendar';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { CodeBlock } from '../../CodeBlock';\nimport { callbacksCode } from './calendar-story-data';\n\nfunction today(hour: number, minute = 0): Date {\n  const d = new Date();\n  d.setHours(hour, minute, 0, 0);\n  return d;\n}\n\nconst initialEntries: CalendarEntry[] = [\n  { id: 'drag-1', title: 'Drag Me!', start: today(9, 0), end: today(10, 0), color: '#3b82f6', editable: true },\n  { id: 'drag-2', title: 'Resize Me!', start: today(11, 0), end: today(12, 0), color: '#8b5cf6', editable: true },\n  { id: 'drag-3', title: 'Fixed Entry', start: today(14, 0), end: today(15, 0), color: '#6b7280', editable: false },\n];\n\nconst DragDropResize: React.FC = () => {\n  const [entries, setEntries] = useState<CalendarEntry[]>(initialEntries);\n  const [lastAction, setLastAction] = useState('');\n\n  return (\n    <>\n      <ComponentDemo title=\"Drag, Drop & Resize\" description=\"Entries marked as editable can be moved and resized. The fixed entry cannot be moved.\" centered={false}>\n        {lastAction && (\n          <div className=\"mb-3 px-3 py-2 bg-blue-50 dark:bg-blue-900/20 rounded text-sm text-blue-700 dark:text-blue-300\">\n            {lastAction}\n          </div>\n        )}\n        <div style={{ height: 550, width: '100%' }}>\n          <Calendar\n            entries={entries}\n            initialView={ViewMode.timeGridDay}\n            height=\"100%\"\n            editable\n            selectable\n            nowIndicator\n            visibleHoursStart={7}\n            visibleHoursEnd={18}\n            onEntryDrop={(info) => {\n              setEntries(prev => prev.map(e =>\n                e.id === info.entry.id\n                  ? { ...e, start: info.newStart, end: info.newEnd }\n                  : e\n              ));\n              setLastAction(`Moved \"${info.entry.title}\" to ${info.newStart.toLocaleTimeString()}`);\n            }}\n            onEntryResize={(info) => {\n              setEntries(prev => prev.map(e =>\n                e.id === info.entry.id\n                  ? { ...e, start: info.newStart, end: info.newEnd }\n                  : e\n              ));\n              setLastAction(`Resized \"${info.entry.title}\" to ${info.newStart.toLocaleTimeString()} - ${info.newEnd.toLocaleTimeString()}`);\n            }}\n            onDateSelect={(info) => {\n              setLastAction(`Selected: ${info.start.toLocaleTimeString()} - ${info.end.toLocaleTimeString()}`);\n            }}\n          />\n        </div>\n      </ComponentDemo>\n      <div className=\"mt-4\">\n        <CodeBlock title=\"Event Callbacks\" code={callbacksCode} />\n      </div>\n    </>\n  );\n};\n\nexport default DragDropResize;\n"
        },
        {
          "title": "ExternalDragDrop",
          "code": "import React, { useState, useCallback } from 'react';\nimport { Calendar, ViewMode } from '../../../components/calendar';\nimport type { CalendarEntry } from '../../../components/calendar';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { CodeBlock } from '../../CodeBlock';\nimport { externalDragItems, externalDragCode } from './calendar-story-data';\n\nfunction today(hour: number, minute = 0): Date {\n  const d = new Date();\n  d.setHours(hour, minute, 0, 0);\n  return d;\n}\n\nconst initialEntries: CalendarEntry[] = [\n  { id: 'existing-1', title: 'Existing Meeting', start: today(10, 0), end: today(11, 0), color: '#6b7280' },\n];\n\nlet nextId = 100;\n\nconst ExternalDragDrop: React.FC = () => {\n  const [entries, setEntries] = useState<CalendarEntry[]>(initialEntries);\n  const [lastAction, setLastAction] = useState('');\n\n  const handleDragStart = useCallback((e: React.DragEvent, item: typeof externalDragItems[0]) => {\n    e.dataTransfer.setData('application/json', JSON.stringify(item));\n    e.dataTransfer.effectAllowed = 'copy';\n  }, []);\n\n  const handleExternalDrop = useCallback((info: { date: Date; allDay: boolean; data: DataTransfer | null }) => {\n    if (!info.data) return;\n    try {\n      const raw = info.data.getData('application/json');\n      if (!raw) return;\n      const item = JSON.parse(raw);\n      const start = info.date;\n      const end = new Date(start.getTime() + (item.duration || 60) * 60000);\n      const newEntry: CalendarEntry = {\n        id: `ext-drop-${nextId++}`,\n        title: item.title,\n        start,\n        end,\n        color: item.color,\n        allDay: info.allDay,\n        editable: true,\n      };\n      setEntries(prev => [...prev, newEntry]);\n      setLastAction(`Dropped \"${item.title}\" at ${start.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}`);\n    } catch {\n      setLastAction('Invalid drop data');\n    }\n  }, []);\n\n  return (\n    <>\n      <ComponentDemo title=\"External Drag & Drop\" description=\"Drag items from the sidebar into the calendar to create new entries.\" centered={false}>\n        <div className=\"flex flex-col md:flex-row gap-4\" style={{ width: '100%' }}>\n          <div className=\"flex-shrink-0 md:w-48 space-y-2\">\n            <h4 className=\"text-xs font-semibold text-gray-500 uppercase tracking-wide mb-2\">Drag these into calendar</h4>\n            {externalDragItems.map(item => (\n              <div\n                key={item.id}\n                draggable\n                onDragStart={(e) => handleDragStart(e, item)}\n                className=\"flex items-center gap-2 px-3 py-2 rounded-md border border-gray-200 dark:border-gray-700 cursor-grab active:cursor-grabbing select-none hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors\"\n              >\n                <span className=\"w-3 h-3 rounded-full flex-shrink-0\" style={{ background: item.color }} />\n                <span className=\"text-sm font-medium\">{item.title}</span>\n                <span className=\"text-xs text-gray-400 ml-auto\">{item.duration}m</span>\n              </div>\n            ))}\n          </div>\n          <div className=\"flex-1 min-w-0\">\n            {lastAction && (\n              <div className=\"mb-2 px-3 py-1.5 bg-blue-50 dark:bg-blue-900/20 rounded text-xs text-blue-700 dark:text-blue-300\">\n                {lastAction}\n              </div>\n            )}\n            <div style={{ height: 500, width: '100%' }}>\n              <Calendar\n                entries={entries}\n                initialView={ViewMode.timeGridDay}\n                height=\"100%\"\n                editable\n                visibleHoursStart={7}\n                visibleHoursEnd={19}\n                nowIndicator\n                onExternalDrop={handleExternalDrop}\n                onEntryDrop={(info) => {\n                  setEntries(prev => prev.map(e =>\n                    e.id === info.entry.id ? { ...e, start: info.newStart, end: info.newEnd } : e\n                  ));\n                }}\n              />\n            </div>\n          </div>\n        </div>\n      </ComponentDemo>\n      <div className=\"mt-4\">\n        <CodeBlock title=\"External Drag & Drop\" code={externalDragCode} />\n      </div>\n    </>\n  );\n};\n\nexport default ExternalDragDrop;\n"
        },
        {
          "title": "ImperativeApi",
          "code": "import React, { useRef, useState } from 'react';\nimport { Calendar, ViewMode } from '../../../components/calendar';\nimport type { CalendarApi } from '../../../components/calendar';\nimport { Button } from '../../../components/Button';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { CodeBlock } from '../../CodeBlock';\nimport { sampleEntries, imperativeApiCode } from './calendar-story-data';\n\nconst ImperativeApi: React.FC = () => {\n  const apiRef = useRef<CalendarApi>(null);\n  const [viewInfo, setViewInfo] = useState('');\n\n  return (\n    <>\n      <ComponentDemo title=\"Imperative API\" description=\"Control the calendar programmatically using a ref.\" centered={false}>\n        <div className=\"flex flex-wrap gap-2 mb-4\">\n          <Button label=\"Previous\" size=\"xs\" layout=\"outlined\" onClick={() => apiRef.current?.prev()} />\n          <Button label=\"Today\" size=\"xs\" variant=\"primary\" onClick={() => apiRef.current?.today()} />\n          <Button label=\"Next\" size=\"xs\" layout=\"outlined\" onClick={() => apiRef.current?.next()} />\n          <Button label=\"Month View\" size=\"xs\" layout=\"outlined\" onClick={() => apiRef.current?.changeView(ViewMode.dayGridMonth)} />\n          <Button label=\"Week View\" size=\"xs\" layout=\"outlined\" onClick={() => apiRef.current?.changeView(ViewMode.timeGridWeek)} />\n          <Button label=\"Day View\" size=\"xs\" layout=\"outlined\" onClick={() => apiRef.current?.changeView(ViewMode.timeGridDay)} />\n          <Button\n            label=\"Get View Info\"\n            size=\"xs\"\n            variant=\"info\"\n            onClick={() => {\n              const info = apiRef.current?.getView();\n              if (info) setViewInfo(`${info.mode}: ${info.title}`);\n            }}\n          />\n        </div>\n        {viewInfo && (\n          <div className=\"mb-3 px-3 py-2 bg-gray-100 dark:bg-gray-800 rounded text-sm\">\n            {viewInfo}\n          </div>\n        )}\n        <div style={{ height: 500, width: '100%' }}>\n          <Calendar\n            entries={sampleEntries}\n            initialView={ViewMode.timeGridWeek}\n            height=\"100%\"\n            apiRef={apiRef}\n            nowIndicator\n          />\n        </div>\n      </ComponentDemo>\n      <div className=\"mt-4\">\n        <CodeBlock title=\"Imperative API\" code={imperativeApiCode} />\n      </div>\n    </>\n  );\n};\n\nexport default ImperativeApi;\n"
        },
        {
          "title": "NavigationPickerDemo",
          "code": "import React from 'react';\nimport { Calendar, ViewMode } from '../../../components/calendar';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { CodeBlock } from '../../CodeBlock';\nimport { sampleEntries } from './calendar-story-data';\n\nconst navPickerCode = `<Calendar\n  entries={entries}\n  initialView=\"timeGridWeek\"\n  showNavigationPicker\n  firstDayOfWeek={1}\n  nowIndicator\n/>\n\n// The picker auto-selects the right mode:\n// - Month views → month picker\n// - Week views → week picker\n// - Day views → day picker`;\n\nconst NavigationPickerDemo: React.FC = () => {\n  return (\n    <>\n      <ComponentDemo\n        title=\"Navigation Picker\"\n        description=\"Enable showNavigationPicker to add a date range picker in the toolbar. It auto-selects week/month/day mode based on the current view. Try switching views to see the picker mode change.\"\n        centered={false}\n      >\n        <div style={{ height: 550, width: '100%' }}>\n          <Calendar\n            entries={sampleEntries}\n            initialView={ViewMode.timeGridWeek}\n            height=\"100%\"\n            showNavigationPicker\n            firstDayOfWeek={1}\n            nowIndicator\n          />\n        </div>\n      </ComponentDemo>\n      <div className=\"mt-4\">\n        <CodeBlock title=\"Navigation Picker\" code={navPickerCode} />\n      </div>\n    </>\n  );\n};\n\nexport default NavigationPickerDemo;\n"
        },
        {
          "title": "PluginSystem",
          "code": "import React, { useState, useRef } from 'react';\nimport { Calendar, ViewMode } from '../../../components/calendar';\nimport type { CalendarPlugin } from '../../../components/calendar';\nimport { defaultPlugins } from '../../../components/calendar/plugins';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { CodeBlock } from '../../CodeBlock';\nimport { sampleEntries, pluginSystemCode } from './calendar-story-data';\n\nconst PluginSystem: React.FC = () => {\n  const [log, setLog] = useState<string[]>([]);\n  const initCalled = useRef(false);\n\n  const [demoPlugin] = useState<CalendarPlugin>(() => ({\n    name: 'demo-toolbar-plugin',\n    toolbarActions: [\n      {\n        id: 'count-entries',\n        label: 'Count',\n        position: 'end',\n        onClick: (api) => {\n          const count = api.getEntries().length;\n          setLog(prev => [...prev.slice(-4), `Visible entries: ${count}`]);\n        },\n      },\n    ],\n    onInit: () => {\n      if (initCalled.current) return;\n      initCalled.current = true;\n      setLog(prev => [...prev, 'Plugin initialized']);\n    },\n  }));\n\n  return (\n    <>\n      <ComponentDemo title=\"Plugin System\" description=\"Extend the calendar with custom plugins that add toolbar actions, views, and entry renderers.\" centered={false}>\n        <div style={{ height: 400, width: '100%' }}>\n          <Calendar\n            entries={sampleEntries}\n            initialView={ViewMode.timeGridWeek}\n            height=\"100%\"\n            plugins={[...defaultPlugins, demoPlugin]}\n            nowIndicator\n          />\n        </div>\n        {log.length > 0 && (\n          <div className=\"mt-3 p-3 bg-gray-100 dark:bg-gray-800 rounded text-xs font-mono space-y-1\">\n            {log.map((msg, i) => (\n              <div key={i}>{msg}</div>\n            ))}\n          </div>\n        )}\n      </ComponentDemo>\n      <div className=\"mt-4\">\n        <CodeBlock title=\"Plugin System\" code={pluginSystemCode} />\n      </div>\n    </>\n  );\n};\n\nexport default PluginSystem;\n"
        },
        {
          "title": "PluginViews",
          "code": "import React, { useRef, useState } from 'react';\nimport { Button } from '../../../components/Button';\nimport type { CalendarApi } from '../../../components/calendar';\nimport { Calendar, ViewMode } from '../../../components/calendar';\nimport {\n    agendaPlugin,\n    listViewPlugin,\n    monthGridPlugin,\n    timeGridCustomPlugin,\n    timeGridPlugin,\n    yearGridPlugin,\n} from '../../../components/calendar/plugins';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { sampleEntries } from './calendar-story-data';\n\nconst plugins = [\n    timeGridPlugin(),\n    monthGridPlugin(),\n    listViewPlugin(),\n    yearGridPlugin(),\n    agendaPlugin({ dayCount: 14 }),\n    timeGridCustomPlugin({ dayCount: 3, label: '3 Days' }),\n];\n\nconst viewButtons: { label: string; value: string }[] = [\n    { label: 'Week', value: ViewMode.timeGridWeek },\n    { label: 'Month', value: ViewMode.dayGridMonth },\n    { label: '3 Days', value: ViewMode.timeGrid3Day },\n    { label: 'Year', value: ViewMode.yearGrid },\n    { label: 'Agenda', value: ViewMode.agenda },\n    { label: 'Month List', value: ViewMode.listMonth },\n];\n\nconst pluginViewCode = `import {\n  Calendar,\n  timeGridPlugin, monthGridPlugin,\n  yearGridPlugin, agendaPlugin,\n  timeGridCustomPlugin,\n} from 'fluxo-ui';\n\n// Only bundle the views you need\nconst plugins = [\n  timeGridPlugin(),        // timeGridWeek + timeGridDay\n  monthGridPlugin(),       // dayGridMonth\n  yearGridPlugin(),        // yearGrid (12-month overview)\n  agendaPlugin({ dayCount: 14 }),  // 2-week agenda\n  timeGridCustomPlugin({ dayCount: 3, label: '3 Days' }),\n];\n\n<Calendar\n  plugins={plugins}\n  initialView=\"timeGridWeek\"\n  entries={entries}\n/>`;\n\nconst headerToolbarViewsCode = `// Only show specific views in the toolbar dropdown\n<Calendar\n  headerToolbarViews={['timeGridWeek', 'dayGridMonth', 'yearGrid']}\n  entries={entries}\n/>`;\n\nconst customPluginCode = `import { createViewPlugin, defineView } from 'fluxo-ui';\n\n// Build your own view\nconst myView = defineView({\n  name: 'myCustomView',\n  label: 'My View',\n  component: MyViewComponent,  // React component with ViewProps\n  getDateRange: (date, firstDayOfWeek) => ({ start, end }),\n  getTitle: (range) => 'My Custom Title',\n  navigate: (date, dir) =>\n    dir === 'prev' ? subDays(date, 7) : addDays(date, 7),\n});\n\nconst myPlugin = createViewPlugin({\n  name: 'my-plugin',\n  views: [myView],\n});\n\n<Calendar plugins={[myPlugin]} initialView=\"myCustomView\" />`;\n\nconst PluginViews: React.FC = () => {\n    const apiRef = useRef<CalendarApi>(null);\n    const [currentView, setCurrentView] = useState<string>(ViewMode.timeGridWeek);\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Plugin-Based Views\"\n                description=\"Views are tree-shakeable plugins. Only import what you need — unused views won't be bundled. New views: Year Grid, Agenda, and custom N-day time grids.\"\n                centered={false}\n            >\n                <div className=\"flex flex-wrap gap-2 mb-4\">\n                    {viewButtons.map((opt) => (\n                        <Button\n                            key={opt.value}\n                            label={opt.label}\n                            size=\"xs\"\n                            variant={currentView === opt.value ? 'primary' : 'default'}\n                            layout={currentView === opt.value ? 'default' : 'outlined'}\n                            onClick={() => {\n                                apiRef.current?.changeView(opt.value);\n                                setCurrentView(opt.value);\n                            }}\n                        />\n                    ))}\n                </div>\n                <div style={{ height: 550, width: '100%' }}>\n                    <Calendar\n                        entries={sampleEntries}\n                        initialView={ViewMode.timeGridWeek}\n                        height=\"100%\"\n                        apiRef={apiRef}\n                        plugins={plugins}\n                        nowIndicator\n                        onViewChange={setCurrentView}\n                    />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4 space-y-4\">\n                <CodeBlock title=\"Plugin-based view selection\" code={pluginViewCode} />\n                <CodeBlock title=\"Restrict toolbar views via headerToolbarViews\" code={headerToolbarViewsCode} />\n                <CodeBlock title=\"Create your own custom view plugin\" code={customPluginCode} />\n            </div>\n        </>\n    );\n};\n\nexport default PluginViews;\n"
        },
        {
          "title": "TimeGridConfig",
          "code": "import React, { useState } from 'react';\nimport { Calendar, ViewMode } from '../../../components/calendar';\nimport { Dropdown } from '../../../components/Dropdown';\nimport { InputSwitch } from '../../../components/InputSwitch';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { CodeBlock } from '../../CodeBlock';\nimport { sampleEntries, configCode } from './calendar-story-data';\n\nconst slotOptions = [\n  { label: '15 min', value: 15 },\n  { label: '30 min', value: 30 },\n  { label: '60 min', value: 60 },\n];\n\nconst formatOptions = [\n  { label: '12h', value: '12h' },\n  { label: '24h', value: '24h' },\n];\n\nconst TimeGridConfig: React.FC = () => {\n  const [slotDuration, setSlotDuration] = useState(30);\n  const [timeFormat, setTimeFormat] = useState<'12h' | '24h'>('12h');\n  const [rowBanding, setRowBanding] = useState(false);\n\n  return (\n    <>\n      <ComponentDemo title=\"Time Grid Configuration\" description=\"Configure slot duration, visible hours, business hours, time format, and more.\" centered={false}>\n        <div className=\"flex flex-wrap gap-4 mb-4 items-center\">\n          <div className=\"flex items-center gap-2\">\n            <span className=\"text-xs font-medium\">Slot:</span>\n            <Dropdown\n              value={slotDuration}\n              options={slotOptions}\n              onChange={(e) => setSlotDuration(e.value)}\n              size=\"sm\"\n            />\n          </div>\n          <div className=\"flex items-center gap-2\">\n            <span className=\"text-xs font-medium\">Format:</span>\n            <Dropdown\n              value={timeFormat}\n              options={formatOptions}\n              onChange={(e) => setTimeFormat(e.value)}\n              size=\"sm\"\n            />\n          </div>\n          <div className=\"flex items-center gap-2\">\n            <span className=\"text-xs font-medium\">Row Banding:</span>\n            <InputSwitch checked={rowBanding} onChange={(e) => setRowBanding(e.value)} />\n          </div>\n        </div>\n        <div style={{ height: 550, width: '100%' }}>\n          <Calendar\n            entries={sampleEntries}\n            initialView={ViewMode.timeGridWeek}\n            height=\"100%\"\n            slotDuration={slotDuration}\n            visibleHoursStart={7}\n            visibleHoursEnd={21}\n            timeFormat={timeFormat}\n            rowBanding={rowBanding}\n            businessHours={{\n              daysOfWeek: [1, 2, 3, 4, 5],\n              startTime: '09:00',\n              endTime: '17:00',\n            }}\n            nowIndicator\n          />\n        </div>\n      </ComponentDemo>\n      <div className=\"mt-4\">\n        <CodeBlock title=\"Configuration\" code={configCode} />\n      </div>\n    </>\n  );\n};\n\nexport default TimeGridConfig;\n"
        },
        {
          "title": "ViewModes",
          "code": "import React, { useRef, useState } from 'react';\nimport { Calendar, ViewMode } from '../../../components/calendar';\nimport type { CalendarApi, CalendarViewMode } from '../../../components/calendar';\nimport { Button } from '../../../components/Button';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { sampleEntries } from './calendar-story-data';\n\nconst viewOptions: { label: string; value: CalendarViewMode }[] = [\n  { label: 'Month Grid', value: ViewMode.dayGridMonth },\n  { label: 'Week Time Grid', value: ViewMode.timeGridWeek },\n  { label: 'Day Time Grid', value: ViewMode.timeGridDay },\n  { label: 'Week Day Grid', value: ViewMode.dayGridWeek },\n  { label: 'Day Grid', value: ViewMode.dayGridDay },\n  { label: 'Month List', value: ViewMode.listMonth },\n  { label: 'Week List', value: ViewMode.listWeek },\n  { label: 'Day List', value: ViewMode.listDay },\n  { label: 'Multi-Month', value: ViewMode.multiMonth },\n  { label: 'Scroll Month', value: ViewMode.scrollMonth },\n];\n\nconst ViewModes: React.FC = () => {\n  const apiRef = useRef<CalendarApi>(null);\n  const [currentView, setCurrentView] = useState<CalendarViewMode>(ViewMode.timeGridWeek);\n\n  return (\n    <ComponentDemo title=\"View Modes\" description=\"All 8 built-in view modes. Click buttons to switch.\" centered={false}>\n      <div className=\"flex flex-wrap gap-2 mb-4\">\n        {viewOptions.map(opt => (\n          <Button\n            key={opt.value}\n            label={opt.label}\n            size=\"xs\"\n            variant={currentView === opt.value ? 'primary' : 'default'}\n            layout={currentView === opt.value ? 'default' : 'outlined'}\n            onClick={() => {\n              apiRef.current?.changeView(opt.value);\n              setCurrentView(opt.value);\n            }}\n          />\n        ))}\n      </div>\n      <div style={{ height: 550, width: '100%' }}>\n        <Calendar\n          entries={sampleEntries}\n          initialView={ViewMode.timeGridWeek}\n          height=\"100%\"\n          apiRef={apiRef}\n          nowIndicator\n          onViewChange={setCurrentView}\n        />\n      </div>\n    </ComponentDemo>\n  );\n};\n\nexport default ViewModes;\n"
        }
      ],
      "props": {
        "calendarProps": {
          "entries": {
            "type": "CalendarEntry[]",
            "default": "[]",
            "description": "Array of calendar entries to display"
          },
          "initialView": {
            "type": "CalendarViewMode",
            "default": "timeGridWeek",
            "description": "Starting view mode"
          },
          "initialDate": {
            "type": "Date | string",
            "default": "new Date()",
            "description": "Starting date for navigation"
          },
          "plugins": {
            "type": "CalendarPlugin[]",
            "default": "defaultPlugins",
            "description": "Array of view/feature plugins. When omitted, all built-in views are registered. Pass specific plugins to tree-shake unused views."
          },
          "headerToolbarViews": {
            "type": "string[]",
            "description": "Restrict which view modes appear in the toolbar dropdown. Array of view name strings (e.g. [\\\"timeGridWeek\\\", \\\"dayGridMonth\\\"]). When omitted, all registered views are shown."
          },
          "slotDuration": {
            "type": "number",
            "default": "30",
            "description": "Time grid slot interval in minutes"
          },
          "visibleHoursStart": {
            "type": "number",
            "default": "0",
            "description": "First visible hour (0-23)"
          },
          "visibleHoursEnd": {
            "type": "number",
            "default": "24",
            "description": "Last visible hour (1-24)"
          },
          "businessHours": {
            "type": "BusinessHours",
            "default": "Mon-Fri 9-17",
            "description": "Working days and hours config"
          },
          "firstDayOfWeek": {
            "type": "number",
            "default": "0",
            "description": "Week start day (0=Sun, 1=Mon)"
          },
          "hiddenDays": {
            "type": "number[]",
            "default": "[]",
            "description": "Days to hide from views"
          },
          "timeFormat": {
            "type": "'12h' | '24h'",
            "default": "12h",
            "description": "Time display format"
          },
          "editable": {
            "type": "boolean",
            "default": "false",
            "description": "Global drag/drop/resize default"
          },
          "selectable": {
            "type": "boolean",
            "default": "true",
            "description": "Enable time range selection"
          },
          "creatable": {
            "type": "boolean",
            "default": "false",
            "description": "Enable entry creation via drag (time grid) or double-click (month/day grid). Fires onEntryCreate callback."
          },
          "slotHeight": {
            "type": "number",
            "default": "24",
            "description": "Height in pixels of each time slot in time grid views. Lower values make the grid more compact."
          },
          "onEntryCreate": {
            "type": "(info: EntryCreateInfo) => void",
            "description": "Called when a new entry is created via drag or double-click. Receives { start, end, allDay, view }."
          },
          "eventMinDuration": {
            "type": "number",
            "default": "0",
            "description": "Minimum entry duration in minutes when creating/resizing (0 = no limit)."
          },
          "eventMaxDuration": {
            "type": "number",
            "default": "0",
            "description": "Maximum entry duration in minutes when creating/resizing (0 = no limit)."
          },
          "eventDefaultDuration": {
            "type": "number",
            "default": "60",
            "description": "Default duration in minutes for entries created via click (not drag)."
          },
          "eventDurationEditable": {
            "type": "boolean",
            "default": "true",
            "description": "Whether entries can be resized. Separate from editable (move)."
          },
          "eventStartEditable": {
            "type": "boolean",
            "default": "true",
            "description": "Whether entries can be moved. Separate from editable (resize)."
          },
          "eventOverlap": {
            "type": "boolean",
            "default": "true",
            "description": "Whether dragged/resized entries can overlap existing entries."
          },
          "eventClassNames": {
            "type": "(entry) => string | string[]",
            "description": "Dynamic CSS class names per entry for conditional styling."
          },
          "eventConstraint": {
            "type": "(info) => boolean",
            "description": "Restrict event drag/resize to specific time ranges (e.g., only within business hours)."
          },
          "eventDataTransform": {
            "type": "(entry) => CalendarEntry",
            "description": "Transform function applied to all entry data before rendering."
          },
          "entryOrder": {
            "type": "(a, b) => number",
            "description": "Custom sort function for ordering overlapping entries."
          },
          "selectMinDistance": {
            "type": "number",
            "default": "0",
            "description": "Min drag distance in pixels before selection starts."
          },
          "selectOverlap": {
            "type": "boolean",
            "default": "true",
            "description": "Whether selections can overlap existing entries."
          },
          "selectAllow": {
            "type": "(info) => boolean",
            "description": "Conditionally prevent selection of certain time ranges."
          },
          "selectMirror": {
            "type": "boolean",
            "default": "false",
            "description": "Show a mirror entry during drag-to-create instead of selection highlight."
          },
          "eventAllow": {
            "type": "(info) => boolean",
            "description": "Conditionally prevent entry drop/resize at certain times."
          },
          "scrollTime": {
            "type": "string",
            "default": "08:00",
            "description": "Initial scroll position for time grid views (HH:MM format)."
          },
          "longPressDelay": {
            "type": "number",
            "default": "1000",
            "description": "Milliseconds to hold before touch becomes drag on mobile."
          },
          "moreLinkClick": {
            "type": "'popover' | 'day' | callback",
            "default": "popover",
            "description": "Behavior when +N more is clicked in month view."
          },
          "weekNumberClick": {
            "type": "(weekNum, date, event) => void",
            "description": "Callback when a week number is clicked."
          },
          "dayHeaderClick": {
            "type": "(date, event) => void",
            "description": "Callback when a day column header is clicked in time grid."
          },
          "dateAlignment": {
            "type": "number",
            "default": "0",
            "description": "Navigate by N days instead of view-width (0 = use view default)."
          },
          "allDaySlotMaxHeight": {
            "type": "number",
            "default": "0",
            "description": "Max height in px for the all-day row (0 = unlimited)."
          },
          "dayMinWidth": {
            "type": "number",
            "default": "0",
            "description": "Min column width in px for day columns in time grid (0 = auto)."
          },
          "dayMinHeight": {
            "type": "number",
            "default": "0",
            "description": "Min height in px for day cells in month view (0 = auto)."
          },
          "slotLabelInterval": {
            "type": "number",
            "default": "0",
            "description": "Interval in minutes at which slot labels appear in the time gutter. 0 (default) = label only at the start of each hour. Must be a positive divisor of 60 (e.g. 15, 30) when set. Use slotDuration to label every slot or 2*slotDuration for every other slot."
          },
          "loading": {
            "type": "boolean",
            "default": "false",
            "description": "Show a loading indicator overlay on the calendar."
          },
          "stickyHeaderDates": {
            "type": "boolean",
            "default": "true",
            "description": "Keep day/date headers sticky when scrolling the time grid."
          },
          "weekText": {
            "type": "string",
            "default": "''",
            "description": "Prefix for week numbers display."
          },
          "fixedWeekCount": {
            "type": "boolean",
            "default": "true",
            "description": "Always show 6 weeks in month grid."
          },
          "expandRows": {
            "type": "boolean",
            "default": "false",
            "description": "Expand month grid rows to fill available space."
          },
          "multiMonthCount": {
            "type": "number",
            "default": "3",
            "description": "Number of months to display in multi-month view."
          },
          "nowIndicatorInterval": {
            "type": "number",
            "default": "60000",
            "description": "Update frequency in ms for the now indicator line."
          },
          "dayPopoverFormat": {
            "type": "string",
            "default": "'EEEE, MMMM d'",
            "description": "Date format in overflow popover header."
          },
          "allDayText": {
            "type": "string",
            "default": "'all-day'",
            "description": "Label text for the all-day row in time grid and overflow popover."
          },
          "displayEventTime": {
            "type": "boolean",
            "default": "true",
            "description": "Whether to show the start time on entries in the default entry renderer."
          },
          "nowIndicator": {
            "type": "boolean",
            "default": "true",
            "description": "Show current time line"
          },
          "navLinks": {
            "type": "boolean",
            "default": "true",
            "description": "Date headers as navigation links"
          },
          "compact": {
            "type": "boolean",
            "default": "false",
            "description": "Compact/embedded mode"
          },
          "rowBanding": {
            "type": "boolean",
            "default": "false",
            "description": "Alternate row colors on time grid"
          },
          "showNavigationPicker": {
            "type": "boolean",
            "default": "false",
            "description": "Show a DateRangePicker in the toolbar for quick date navigation. Auto-selects week/month/day mode based on current view."
          },
          "navigationPickerIconOnly": {
            "type": "boolean",
            "default": "false",
            "description": "When true, shows only a calendar icon for the navigation picker (title remains visible). When false (default), the picker replaces the title with header-styled text."
          },
          "renderToolbarEnd": {
            "type": "(components) => ReactNode",
            "description": "Custom render for the toolbar end section. Receives { viewSwitcher, pluginActions } as ReactNodes to compose alongside custom components."
          },
          "dateBackgrounds": {
            "type": "DateBackground[]",
            "description": "Highlight specific dates with background colors. Array of {date, color}."
          },
          "dateRangeBackgrounds": {
            "type": "DateRangeBackground[]",
            "description": "Highlight date ranges with background colors. Array of {start, end, color}."
          },
          "loadingRanges": {
            "type": "DateLoadingRange[]",
            "description": "Show shimmer loaders for dates being loaded. Array of {start, end}."
          },
          "hideEmptyDays": {
            "type": "boolean",
            "default": "false",
            "description": "List view only: when true, days that contain no entries are filtered out so users only see days with data. When all days in the range are empty, the empty state is rendered instead."
          },
          "emptyMessage": {
            "type": "ReactNode",
            "default": "'No entries to display'",
            "description": "Message shown when the entire list view has zero entries for the visible range. Pass a string or any ReactNode for richer content."
          },
          "emptyDayMessage": {
            "type": "ReactNode",
            "default": "'No entries'",
            "description": "Inline message inside a day group when that day is empty. Only shown when hideEmptyDays is false."
          },
          "renderEmpty": {
            "type": "(info: { dateRange }) => ReactNode",
            "description": "Render-prop for a fully custom empty state. When provided, overrides the default icon + emptyMessage."
          },
          "showAllDayRow": {
            "type": "'auto' | 'always'",
            "default": "auto",
            "description": "Time grid all-day row visibility. 'auto' (default) hides the row when there are no all-day entries. 'always' keeps the row visible so the gutter label and day slots remain available as drop targets / visual anchors."
          },
          "titleFormat": {
            "type": "string",
            "description": "Custom date-fns format string for the toolbar title."
          },
          "dayHeaderFormat": {
            "type": "string",
            "default": "d",
            "description": "Format for day numbers in headers."
          },
          "weekDayHeaderFormat": {
            "type": "string",
            "default": "EEE",
            "description": "Format for weekday names in headers."
          },
          "dayHeaderLayout": {
            "type": "'stacked' | 'inline'",
            "default": "stacked",
            "description": "Layout for time-grid day headers. 'stacked' shows weekday on top and large day-number below (modern, spacious). 'inline' shows them on a single compact line — when dayHeaderFormat is provided it is used verbatim (e.g. 'EEE, dd/MM' → 'Sun, 17/05'); otherwise weekday + day-number are joined."
          },
          "onExternalDrop": {
            "type": "(info, event) => void",
            "description": "Called when an external item is dropped onto the calendar."
          },
          "height": {
            "type": "string | number",
            "default": "100%",
            "description": "Calendar container height"
          },
          "renderEntry": {
            "type": "(entry, context) => ReactNode",
            "description": "Custom entry template"
          },
          "renderToolbar": {
            "type": "(defaults, api) => ReactNode",
            "description": "Custom toolbar rendering"
          },
          "onEntryClick": {
            "type": "(entry, event) => void",
            "description": "Entry click callback"
          },
          "onDateSelect": {
            "type": "(info, event) => void",
            "description": "Time range selection callback"
          },
          "onEntryDrop": {
            "type": "(info, event) => void",
            "description": "Drag-drop callback"
          },
          "onEntryResize": {
            "type": "(info, event) => void",
            "description": "Resize callback"
          },
          "onViewChange": {
            "type": "(view) => void",
            "description": "View mode change callback"
          },
          "onDateRangeChange": {
            "type": "(range) => void",
            "description": "Date range change callback"
          },
          "onTitleChange": {
            "type": "(title: string) => void",
            "description": "Fires whenever the toolbar title changes (e.g. after navigation or a view change). Useful when the built-in toolbar is hidden (hideToolbar) and the host wants to render the title in its own header bar."
          },
          "apiRef": {
            "type": "RefObject<CalendarApi>",
            "description": "Ref for imperative API access"
          }
        }
      },
      "storyDir": "calendar"
    },
    "CanvasDraw": {
      "name": "CanvasDraw",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "ControlledMode",
          "code": "import cn from 'classnames';\nimport React, { useState } from 'react';\nimport CanvasDraw from '../../../components/canvas-draw/CanvasDraw';\nimport type { DrawItem } from '../../../components/canvas-draw/canvas-draw-types';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\n\nconst code = `const [items, setItems] = useState<DrawItem[]>([]);\n\n<CanvasDraw\n  background={{ type: 'color', color: '#fff7ed' }}\n  items={items}\n  onItemsChange={setItems}\n/>\n\n// Uncontrolled — just omit items prop:\n<CanvasDraw background={{ type: 'color', color: '#fff' }} />`;\n\nconst ControlledMode: React.FC = () => {\n    const { isDark } = useStoryTheme();\n    const [controlledItems, setControlledItems] = useState<DrawItem[]>([]);\n\n    return (\n        <>\n            <ComponentDemo title=\"Controlled — Item Count Tracked Externally\" centered={false}>\n                <div className=\"space-y-3\">\n                    <CanvasDraw\n                        background={{ type: 'color', color: '#fff7ed' }}\n                        items={controlledItems}\n                        onItemsChange={setControlledItems}\n                        style={{ height: 380 }}\n                    />\n                    <div className={cn('text-sm px-4 py-2 rounded border', {\n                        'border-blue-800 bg-blue-900/30 text-blue-300': isDark,\n                        'border-blue-200 bg-blue-50 text-blue-800': !isDark,\n                    })}>\n                        Items drawn: <strong>{controlledItems.length}</strong>\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default ControlledMode;\n"
        },
        {
          "title": "DrawingCanvas",
          "code": "import React, { useState } from 'react';\nimport CanvasDraw from '../../../components/canvas-draw/CanvasDraw';\nimport type { DrawItem } from '../../../components/canvas-draw/canvas-draw-types';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<CanvasDraw\n  background={{ type: 'color', color: '#f8f9fa' }}\n  items={items}\n  onItemsChange={setItems}\n  defaultTool=\"freehand\"\n  style={{ height: 350 }}\n/>`;\n\nconst DrawingCanvas: React.FC = () => {\n    const [drawingItems, setDrawingItems] = useState<DrawItem[]>([]);\n\n    return (\n        <>\n            <ComponentDemo title=\"Blank Canvas Drawing\" centered={false}>\n                <CanvasDraw\n                    background={{ type: 'color', color: '#f8f9fa' }}\n                    items={drawingItems}\n                    onItemsChange={setDrawingItems}\n                    defaultTool=\"freehand\"\n                    style={{ height: 350 }}\n                />\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default DrawingCanvas;\n"
        },
        {
          "title": "ExportDemo",
          "code": "import cn from 'classnames';\nimport React, { useCallback, useState } from 'react';\nimport CanvasDraw from '../../../components/canvas-draw/CanvasDraw';\nimport type { ImageExportFormat } from '../../../components/canvas-draw/canvas-draw-types';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\n\nconst code = `const handleExport = (dataUrl: string, format: ImageExportFormat) => {\n  // dataUrl contains the image data\n  // SVG export works without extra dependencies\n  // PNG/JPG/WebP requires: npm install html2canvas\n  console.log(\\`Exported \\${format}:\\`, dataUrl.length, 'chars');\n};\n\n<CanvasDraw\n  background={{ type: 'color', color: '#f0f9ff' }}\n  onExport={handleExport}\n  features={{ export: true }}\n/>`;\n\nconst ExportDemo: React.FC = () => {\n    const { isDark } = useStoryTheme();\n    const [exportUrl, setExportUrl] = useState<string | null>(null);\n    const [exportFormat, setExportFormat] = useState<string>('');\n\n    const handleExport = useCallback((dataUrl: string, format: ImageExportFormat) => {\n        setExportUrl(dataUrl);\n        setExportFormat(format);\n    }, []);\n\n    return (\n        <>\n            <ComponentDemo title=\"Export Drawing\" centered={false}>\n                <div className=\"space-y-3\">\n                    <CanvasDraw\n                        background={{ type: 'color', color: '#f0f9ff' }}\n                        onExport={handleExport}\n                        features={{ export: true }}\n                        style={{ height: 380 }}\n                    />\n                    {exportUrl && (\n                        <div className={cn('text-sm px-4 py-2 rounded border', {\n                            'border-green-800 bg-green-900/30 text-green-300': isDark,\n                            'border-green-200 bg-green-50 text-green-800': !isDark,\n                        })}>\n                            Exported as <strong>{exportFormat.toUpperCase()}</strong> — data URL generated ({exportUrl.length} chars)\n                        </div>\n                    )}\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default ExportDemo;\n"
        },
        {
          "title": "FeatureFlags",
          "code": "import React from 'react';\nimport CanvasDraw from '../../../components/canvas-draw/CanvasDraw';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<CanvasDraw\n  background={{ type: 'color', color: '#f0fdf4' }}\n  features={{\n    timing: false,\n    transitions: false,\n    groups: false,\n    export: false,\n    fontControls: false,\n    roundedCorners: false,\n  }}\n/>`;\n\nconst FeatureFlags: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Minimal Toolbar — Drawing Only\" centered={false}>\n            <CanvasDraw\n                background={{ type: 'color', color: '#f0fdf4' }}\n                features={{\n                    timing: false,\n                    transitions: false,\n                    groups: false,\n                    export: false,\n                    fontControls: false,\n                    roundedCorners: false,\n                }}\n                style={{ height: 380 }}\n            />\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} />\n        </div>\n    </>\n);\n\nexport default FeatureFlags;\n"
        },
        {
          "title": "ImageAnnotation",
          "code": "import React, { useState } from 'react';\nimport CanvasDraw from '../../../components/canvas-draw/CanvasDraw';\nimport type { DrawItem } from '../../../components/canvas-draw/canvas-draw-types';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { prebuiltItems, sampleImageUrl } from './canvas-draw-story-data';\n\nconst code = `import { CanvasDraw } from 'fluxo-ui';\nimport type { DrawItem } from 'fluxo-ui';\n\nconst [items, setItems] = useState<DrawItem[]>([]);\n\n<CanvasDraw\n  background={{ type: 'image', src: '/screenshot.png' }}\n  items={items}\n  onItemsChange={setItems}\n  style={{ height: 400 }}\n/>`;\n\nconst ImageAnnotation: React.FC = () => {\n    const [imageItems, setImageItems] = useState<DrawItem[]>(prebuiltItems);\n\n    return (\n        <>\n            <ComponentDemo title=\"Annotate an Image\" centered={false}>\n                <CanvasDraw\n                    background={{ type: 'image', src: sampleImageUrl }}\n                    items={imageItems}\n                    onItemsChange={setImageItems}\n                    style={{ height: 400 }}\n                />\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock title=\"Image Annotation\" code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default ImageAnnotation;\n"
        },
        {
          "title": "MediaTimelineDemo",
          "code": "import React, { useCallback, useState } from 'react';\nimport MediaTimeline from '../../../components/canvas-draw/MediaTimeline';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport type { TimelineGroup, TimelineItem } from './canvas-draw-story-data';\nimport { initialTimelineItems } from './canvas-draw-story-data';\n\nconst code = `import { MediaTimeline } from 'fluxo-ui';\nimport type { TimelineItem, TimelineGroup } from 'fluxo-ui';\n\nconst [items, setItems] = useState<TimelineItem[]>([\n  { id: '1', label: 'Intro', showAtMs: 0, hideAtMs: 3000,\n    groupId: null, transition: 'fade' },\n]);\nconst [groups, setGroups] = useState<TimelineGroup[]>([]);\nconst [selected, setSelected] = useState<string | null>(null);\nconst [currentMs, setCurrentMs] = useState(0);\n\n<MediaTimeline\n  items={items}\n  groups={groups}\n  durationMs={10000}\n  currentMs={currentMs}\n  selectedItemId={selected}\n  onSelectItem={setSelected}\n  onUpdateItem={(id, patch) =>\n    setItems(prev => prev.map(it => it.id === id ? { ...it, ...patch } : it))\n  }\n  onUpdateGroup={(id, patch) =>\n    setGroups(prev => prev.map(g => g.id === id ? { ...g, ...patch } : g))\n  }\n  onAddGroup={() => setGroups(prev => [...prev, { id: \\`g-\\${Date.now()}\\`, label: 'New Group', showAtMs: 0, hideAtMs: null, transition: 'none' }])}\n  onDeleteGroup={(id) => setGroups(prev => prev.filter(g => g.id !== id))}\n  onSeek={setCurrentMs}\n/>`;\n\nconst MediaTimelineDemo: React.FC = () => {\n    const [timelineItems, setTimelineItems] = useState<TimelineItem[]>(initialTimelineItems);\n    const [timelineGroups, setTimelineGroups] = useState<TimelineGroup[]>([]);\n    const [selectedTimelineItem, setSelectedTimelineItem] = useState<string | null>(null);\n    const [currentMs, setCurrentMs] = useState(0);\n\n    const handleTimelineUpdateItem = useCallback((id: string, patch: Partial<TimelineItem>) => {\n        setTimelineItems((prev) => prev.map((it) => (it.id === id ? { ...it, ...patch } : it)));\n    }, []);\n\n    const handleTimelineUpdateGroup = useCallback((id: string, patch: Partial<TimelineGroup>) => {\n        setTimelineGroups((prev) => prev.map((g) => (g.id === id ? { ...g, ...patch } : g)));\n    }, []);\n\n    const handleTimelineAddGroup = useCallback(() => {\n        const newGroup: TimelineGroup = {\n            id: `grp-${Date.now()}`,\n            label: `Group ${timelineGroups.length + 1}`,\n            showAtMs: 0,\n            hideAtMs: null,\n            transition: 'none',\n        };\n        setTimelineGroups((prev) => [...prev, newGroup]);\n    }, [timelineGroups.length]);\n\n    const handleTimelineDeleteGroup = useCallback((id: string) => {\n        setTimelineGroups((prev) => prev.filter((g) => g.id !== id));\n        setTimelineItems((prev) => prev.map((it) => (it.groupId === id ? { ...it, groupId: null } : it)));\n    }, []);\n\n    return (\n        <>\n            <ComponentDemo title=\"Interactive Timeline\" centered={false}>\n                <div style={{ padding: '0 8px 8px' }}>\n                    <MediaTimeline\n                        items={timelineItems}\n                        groups={timelineGroups}\n                        durationMs={10000}\n                        currentMs={currentMs}\n                        selectedItemId={selectedTimelineItem}\n                        onSelectItem={setSelectedTimelineItem}\n                        onUpdateItem={handleTimelineUpdateItem}\n                        onUpdateGroup={handleTimelineUpdateGroup}\n                        onAddGroup={handleTimelineAddGroup}\n                        onDeleteGroup={handleTimelineDeleteGroup}\n                        onSeek={setCurrentMs}\n                    />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default MediaTimelineDemo;\n"
        },
        {
          "title": "ReadOnlyMode",
          "code": "import React from 'react';\nimport CanvasDraw from '../../../components/canvas-draw/CanvasDraw';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { sampleImageUrl, prebuiltItems } from './canvas-draw-story-data';\n\nconst code = `<CanvasDraw\n  background={{ type: 'image', src: '/screenshot.png' }}\n  items={savedItems}\n  isEditing={false}\n/>`;\n\nconst ReadOnlyMode: React.FC = () => (\n    <>\n        <ComponentDemo title=\"View-Only with Pre-drawn Items\" centered={false}>\n            <CanvasDraw\n                background={{ type: 'image', src: sampleImageUrl }}\n                items={prebuiltItems}\n                isEditing={false}\n                style={{ height: 380 }}\n            />\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} />\n        </div>\n    </>\n);\n\nexport default ReadOnlyMode;\n"
        },
        {
          "title": "TimedAnnotations",
          "code": "import React from 'react';\nimport CanvasDraw from '../../../components/canvas-draw/CanvasDraw';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { timedItems } from './canvas-draw-story-data';\n\nconst code = `const items: DrawItem[] = [\n  {\n    id: 'item-1',\n    object: { type: 'rect', /* ... */ },\n    showAtMs: 0,\n    hideAtMs: 3000,\n    transition: 'fade',\n    groupId: null,\n    xPct: 0.1, yPct: 0.15, wPct: 0.3, hPct: 0.3,\n  },\n  {\n    id: 'item-2',\n    object: { type: 'arrow', /* ... */ },\n    showAtMs: 2000,\n    hideAtMs: 5000,\n    transition: 'scale',\n    groupId: null,\n    xPct: 0.5, yPct: 0.2, wPct: 0.3, hPct: 0.3,\n  },\n];\n\n<CanvasDraw\n  background={{ type: 'color', color: '#1a1a2e' }}\n  items={items}\n  currentMs={currentMs}\n  mediaDurationMs={8000}\n  features={{ timing: true, transitions: true, groups: true }}\n/>`;\n\nconst TimedAnnotations: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Timed Items — Enable Timing in Features\" centered={false}>\n            <CanvasDraw\n                background={{ type: 'color', color: '#1a1a2e' }}\n                items={timedItems}\n                currentMs={0}\n                mediaDurationMs={8000}\n                features={{\n                    timing: true,\n                    transitions: true,\n                    groups: true,\n                }}\n                style={{ height: 380 }}\n            />\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} />\n        </div>\n    </>\n);\n\nexport default TimedAnnotations;\n"
        },
        {
          "title": "ToolSubset",
          "code": "import React from 'react';\nimport CanvasDraw from '../../../components/canvas-draw/CanvasDraw';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<CanvasDraw\n  background={{ type: 'color', color: '#faf5ff' }}\n  features={{\n    tools: {\n      select: true,\n      arrow: true,\n      rect: true,\n      freehand: false,\n      line: false,\n      circle: false,\n      text: false,\n      balloon: false,\n      step: false,\n    },\n    timing: false,\n    transitions: false,\n    groups: false,\n  }}\n/>`;\n\nconst ToolSubset: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Arrows & Rectangles Only\" centered={false}>\n            <CanvasDraw\n                background={{ type: 'color', color: '#faf5ff' }}\n                features={{\n                    tools: {\n                        select: true,\n                        arrow: true,\n                        rect: true,\n                        freehand: false,\n                        line: false,\n                        circle: false,\n                        text: false,\n                        balloon: false,\n                        step: false,\n                    },\n                    timing: false,\n                    transitions: false,\n                    groups: false,\n                }}\n                style={{ height: 380 }}\n            />\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} />\n        </div>\n    </>\n);\n\nexport default ToolSubset;\n"
        },
        {
          "title": "ToolbarPlacement",
          "code": "import React from 'react';\nimport CanvasDraw from '../../../components/canvas-draw/CanvasDraw';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `// Toolbar on the bottom\n<CanvasDraw\n  background={{ type: 'color', color: '#eef2ff' }}\n  toolbarPlacement=\"bottom\"\n/>\n\n// Vertical toolbar on the left\n<CanvasDraw\n  background={{ type: 'color', color: '#fef3c7' }}\n  toolbarPlacement=\"left\"\n/>\n\n// Available: 'top' | 'bottom' | 'left' | 'right' | 'none'`;\n\nconst ToolbarPlacement: React.FC = () => (\n    <>\n        <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n            <ComponentDemo title=\"Bottom Toolbar\" centered={false}>\n                <CanvasDraw\n                    background={{ type: 'color', color: '#eef2ff' }}\n                    toolbarPlacement=\"bottom\"\n                    style={{ height: 380 }}\n                />\n            </ComponentDemo>\n            <ComponentDemo title=\"Left Toolbar\" centered={false}>\n                <CanvasDraw\n                    background={{ type: 'color', color: '#fef3c7' }}\n                    toolbarPlacement=\"left\"\n                    style={{ height: 380 }}\n                />\n            </ComponentDemo>\n        </div>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} />\n        </div>\n    </>\n);\n\nexport default ToolbarPlacement;\n"
        }
      ],
      "props": {
        "canvasDrawProps": {
          "background": {
            "type": "CanvasBackground",
            "required": true,
            "description": "Background configuration — image, color, or video reference"
          },
          "items": {
            "type": "DrawItem[]",
            "description": "Controlled items array. When provided, component is controlled"
          },
          "groups": {
            "type": "DrawGroup[]",
            "description": "Controlled groups array for annotation grouping"
          },
          "currentMs": {
            "type": "number",
            "default": "0",
            "description": "Current playback position in milliseconds (for timed annotations)"
          },
          "mediaDurationMs": {
            "type": "number",
            "default": "0",
            "description": "Total media duration in milliseconds"
          },
          "isEditing": {
            "type": "boolean",
            "default": "true",
            "description": "Whether the canvas is in edit mode (shows toolbar, allows drawing)"
          },
          "toolbarPlacement": {
            "type": "'top' | 'bottom' | 'left' | 'right' | 'none'",
            "default": "'top'",
            "description": "Position of the drawing toolbar relative to the canvas"
          },
          "defaultTool": {
            "type": "DrawTool",
            "default": "'select'",
            "description": "Initially active tool when the component mounts"
          },
          "defaultToolDefaults": {
            "type": "Partial<DrawToolDefaults>",
            "description": "Override default stroke color, fill, font settings, etc."
          },
          "features": {
            "type": "CanvasDrawFeatures",
            "default": "{}",
            "description": "Feature flags to enable/disable toolbar sections and tools"
          },
          "className": {
            "type": "string",
            "description": "Additional CSS class for the root element"
          },
          "style": {
            "type": "React.CSSProperties",
            "description": "Inline styles for the root element"
          },
          "onItemsChange": {
            "type": "(items: DrawItem[]) => void",
            "description": "Fires whenever items are added, modified, or removed"
          },
          "onExport": {
            "type": "(dataUrl: string, format: ImageExportFormat) => void",
            "description": "Called when user exports. Enables export buttons when provided"
          }
        },
        "drawItemProps": {
          "id": {
            "type": "string",
            "required": true,
            "description": "Unique identifier for the item"
          },
          "object": {
            "type": "DrawObject",
            "required": true,
            "description": "The drawing object (arrow, rect, circle, text, etc.)"
          },
          "showAtMs": {
            "type": "number",
            "required": true,
            "description": "Time in ms when this item should appear"
          },
          "hideAtMs": {
            "type": "number | null",
            "required": true,
            "description": "Time in ms when this item should hide (null = never)"
          },
          "transition": {
            "type": "DrawTransition",
            "required": true,
            "description": "Animation transition for show/hide (none, fade, scale, slide-*)"
          },
          "groupId": {
            "type": "string | null",
            "required": true,
            "description": "Optional group membership for batch timing"
          },
          "xPct": {
            "type": "number",
            "required": true,
            "description": "Horizontal position as fraction (0-1) of canvas width"
          },
          "yPct": {
            "type": "number",
            "required": true,
            "description": "Vertical position as fraction (0-1) of canvas height"
          },
          "wPct": {
            "type": "number | null",
            "required": true,
            "description": "Width as fraction (0-1). Null for point-based items (steps)"
          },
          "hPct": {
            "type": "number | null",
            "required": true,
            "description": "Height as fraction (0-1). Null for point-based items (steps)"
          }
        },
        "featuresProps": {
          "tools": {
            "type": "ToolConfig",
            "description": "Enable/disable individual tools (select, arrow, rect, circle, etc.)"
          },
          "timing": {
            "type": "boolean",
            "description": "Show timing controls (showAt / hideAt) in toolbar"
          },
          "groups": {
            "type": "boolean",
            "description": "Show group management in toolbar"
          },
          "transitions": {
            "type": "boolean",
            "description": "Show transition selector in toolbar"
          },
          "undo": {
            "type": "boolean",
            "description": "Show undo/redo buttons"
          },
          "export": {
            "type": "boolean",
            "description": "Show export buttons (also requires onExport prop)"
          },
          "clearAll": {
            "type": "boolean",
            "description": "Show clear all button"
          },
          "strokeColor": {
            "type": "boolean",
            "description": "Show stroke color picker"
          },
          "strokeWidth": {
            "type": "boolean",
            "description": "Show stroke width control"
          },
          "fillColor": {
            "type": "boolean",
            "description": "Show fill color picker"
          },
          "fontControls": {
            "type": "boolean",
            "description": "Show font family, size, color, bold/italic/underline"
          },
          "roundedCorners": {
            "type": "boolean",
            "description": "Show rounded corners toggle for rectangles"
          }
        },
        "mediaTimelineProps": {
          "items": {
            "type": "TimelineItem[]",
            "required": true,
            "description": "Timeline items to display as bars"
          },
          "groups": {
            "type": "TimelineGroup[]",
            "required": true,
            "description": "Timeline groups for organizing items"
          },
          "durationMs": {
            "type": "number",
            "required": true,
            "description": "Total duration of the media in milliseconds"
          },
          "currentMs": {
            "type": "number",
            "required": true,
            "description": "Current playback position in milliseconds"
          },
          "selectedItemId": {
            "type": "string | null",
            "required": true,
            "description": "Currently selected item ID"
          },
          "tickCount": {
            "type": "number",
            "default": "10",
            "description": "Number of time ticks to display"
          },
          "defaultItemColor": {
            "type": "string",
            "description": "Default color for items without a group color"
          },
          "onSelectItem": {
            "type": "(id: string | null) => void",
            "required": true,
            "description": "Called when an item is selected or deselected"
          },
          "onUpdateItem": {
            "type": "(id: string, patch: Partial<TimelineItem>) => void",
            "required": true,
            "description": "Called when an item is dragged/resized on the timeline"
          },
          "onUpdateGroup": {
            "type": "(id: string, patch: Partial<TimelineGroup>) => void",
            "required": true,
            "description": "Called when a group is modified"
          },
          "onAddGroup": {
            "type": "() => void",
            "required": true,
            "description": "Called when the add group button is clicked"
          },
          "onDeleteGroup": {
            "type": "(id: string) => void",
            "required": true,
            "description": "Called when a group is deleted"
          },
          "onSeek": {
            "type": "(ms: number) => void",
            "required": true,
            "description": "Called when the user clicks on the timeline to seek"
          }
        }
      },
      "storyDir": "canvas-draw"
    },
    "Card": {
      "name": "Card",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React from 'react';\nimport { Button, Card } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { Card, Button } from 'fluxo-ui';\n\n<Card\n    title=\"Project Atlas\"\n    subtitle=\"Updated 2 hours ago\"\n    actions={<Button label=\"Open\" size=\"xs\" variant=\"primary\" />}\n    footer={<Button label=\"View details\" size=\"sm\" layout=\"plain\" />}\n>\n    Redesign of the main dashboard with improved analytics and deeper drill-downs.\n</Card>`;\n\nconst Body: React.FC<{ children: React.ReactNode }> = ({ children }) => (\n    <span style={{ color: 'var(--eui-text)' }}>{children}</span>\n);\n\nconst BasicUsage: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Basic Card\" description=\"Card with title, subtitle, actions, and footer.\">\n            <div style={{ width: '100%', maxWidth: 420 }}>\n                <Card\n                    title=\"Project Atlas\"\n                    subtitle=\"Updated 2 hours ago\"\n                    actions={<Button label=\"Open\" size=\"xs\" variant=\"primary\" />}\n                    footer={<Button label=\"View details\" size=\"sm\" layout=\"plain\" />}\n                >\n                    <Body>Redesign of the main dashboard with improved analytics and deeper drill-downs.</Body>\n                </Card>\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default BasicUsage;\n"
        },
        {
          "title": "Variants",
          "code": "import React from 'react';\nimport { Card } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<Card variant=\"elevated\" title=\"Elevated\">...</Card>\n<Card variant=\"outlined\" title=\"Outlined\">...</Card>\n<Card variant=\"filled\" title=\"Filled\">...</Card>\n<Card variant=\"ghost\" title=\"Ghost\">...</Card>\n<Card variant=\"interactive\" title=\"Interactive\" onClick={() => {}}>...</Card>`;\n\nconst variants = [\n    { v: 'elevated', desc: 'Soft shadow, no border' },\n    { v: 'outlined', desc: 'Border, no shadow' },\n    { v: 'filled', desc: 'Subtle background' },\n    { v: 'ghost', desc: 'Transparent, just padding' },\n    { v: 'interactive', desc: 'Hover lift + cursor' },\n] as const;\n\nconst Variants: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Variants\" description=\"Five visual styles.\">\n            <div style={{ width: '100%', display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(220px, 1fr))', gap: 14 }}>\n                {variants.map(({ v, desc }) => (\n                    <Card\n                        key={v}\n                        variant={v}\n                        title={v.charAt(0).toUpperCase() + v.slice(1)}\n                        subtitle={desc}\n                        onClick={v === 'interactive' ? () => undefined : undefined}\n                    >\n                        <span style={{ color: 'var(--eui-text-muted)', fontSize: 13 }}>\n                            Card body content lives here.\n                        </span>\n                    </Card>\n                ))}\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default Variants;\n"
        },
        {
          "title": "WithCover",
          "code": "import React from 'react';\nimport { Button, Card } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<Card\n    variant=\"elevated\"\n    padding=\"md\"\n    cover={<img src=\"...\" alt=\"\" />}\n    title=\"Aurora Peak\"\n    subtitle=\"Iceland — 2024\"\n    actions={<Button label=\"Save\" size=\"xs\" variant=\"primary\" />}\n>\n    Seven day hike across the northern ridge.\n</Card>`;\n\nconst IMG =\n    'https://images.unsplash.com/photo-1501785888041-af3ef285b470?auto=format&fit=crop&w=640&q=60';\n\nconst WithCover: React.FC = () => (\n    <>\n        <ComponentDemo title=\"With Cover Media & Orientation\" description=\"Vertical and horizontal layouts with a cover slot.\">\n            <div style={{ width: '100%', display: 'flex', flexWrap: 'wrap', gap: 18 }}>\n                <div style={{ width: 280 }}>\n                    <Card\n                        variant=\"elevated\"\n                        padding=\"md\"\n                        cover={<img src={IMG} alt=\"Mountain\" style={{ height: 160 }} />}\n                        title=\"Aurora Peak\"\n                        subtitle=\"Iceland — 2024\"\n                        actions={<Button label=\"Save\" size=\"xs\" variant=\"primary\" />}\n                    >\n                        <span style={{ color: 'var(--eui-text-muted)', fontSize: 13 }}>Seven day hike across the northern ridge.</span>\n                    </Card>\n                </div>\n                <div style={{ flex: '1 1 420px', minWidth: 0 }}>\n                    <Card\n                        variant=\"outlined\"\n                        orientation=\"horizontal\"\n                        title=\"Desert Dunes\"\n                        subtitle=\"Morocco — 2025\"\n                        cover={<img src={IMG} alt=\"Mountain\" />}\n                        footer={<Button label=\"Book\" size=\"sm\" variant=\"primary\" />}\n                    >\n                        <span style={{ color: 'var(--eui-text-muted)', fontSize: 13 }}>\n                            Guided three-day trek through the Sahara with camel support and star-lit camping.\n                        </span>\n                    </Card>\n                </div>\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default WithCover;\n"
        }
      ],
      "props": {
        "cardProps": {
          "variant": {
            "type": "'elevated' | 'outlined' | 'filled' | 'ghost' | 'interactive'",
            "default": "'outlined'",
            "description": "Visual style."
          },
          "padding": {
            "type": "'none' | 'sm' | 'md' | 'lg'",
            "default": "'md'",
            "description": "Body padding preset."
          },
          "orientation": {
            "type": "'vertical' | 'horizontal'",
            "default": "'vertical'",
            "description": "Layout direction (horizontal puts cover on the left)."
          },
          "size": {
            "type": "'sm' | 'md' | 'lg'",
            "default": "'md'",
            "description": "Overall size preset."
          },
          "title": {
            "type": "ReactNode",
            "description": "Header title."
          },
          "subtitle": {
            "type": "ReactNode",
            "description": "Header subtitle."
          },
          "headingLevel": {
            "type": "1 | 2 | 3 | 4 | 5 | 6",
            "description": "Render the title as the matching <h1>-<h6> element so screen-reader heading navigation works. When omitted, title renders as a styled <div>."
          },
          "actions": {
            "type": "ReactNode",
            "description": "Header right-side actions (usually buttons)."
          },
          "cover": {
            "type": "ReactNode",
            "description": "Top (or left) media slot."
          },
          "footer": {
            "type": "ReactNode",
            "description": "Footer area."
          },
          "loading": {
            "type": "boolean",
            "default": "false",
            "description": "Show shimmer overlay."
          },
          "as": {
            "type": "'div' | 'a' | 'button'",
            "description": "Render as a different element."
          },
          "href": {
            "type": "string",
            "description": "When set, card renders as a link."
          },
          "onClick": {
            "type": "(e) => void",
            "description": "Click handler (makes the card interactive)."
          }
        }
      },
      "storyDir": "card"
    },
    "Carousel": {
      "name": "Carousel",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "AddImages",
          "code": "import React, { useCallback, useEffect, useState } from 'react';\nimport type { CarouselSlide } from '../../../components';\nimport { Carousel } from '../../../components';\nimport { TrashIcon } from '../../../assets/icons';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { Carousel } from 'fluxo-ui';\nimport { TrashIcon } from 'fluxo-ui/icons';\n\nconst addFromFiles = (files: File[]) => {\n  Promise.all(\n    files.map(\n      (file) =>\n        new Promise<CarouselSlide>((resolve) => {\n          const url = URL.createObjectURL(file);\n          resolve({ id: crypto.randomUUID(), type: 'image', src: url, name: file.name });\n        }),\n    ),\n  ).then((next) => setSlides((prev) => [...prev, ...next]));\n};\n\n// Drag-drop and the trailing file-picker tile are handled by the carousel.\n// Forward clipboard paste to the same callback for paste-anywhere support.\nuseEffect(() => {\n  const onPaste = (e: ClipboardEvent) => {\n    const files = Array.from(e.clipboardData?.files ?? []).filter((f) => f.type.startsWith('image/'));\n    if (files.length) addFromFiles(files);\n  };\n  window.addEventListener('paste', onPaste);\n  return () => window.removeEventListener('paste', onPaste);\n}, []);\n\n<Carousel\n  slides={slides}\n  navigation=\"thumbnails\"\n  aspectRatio=\"16/10\"\n  onAddImages={addFromFiles}\n  thumbnailActions={[{ icon: <TrashIcon />, label: 'Delete', variant: 'danger', onClick: (_s, i) => remove(i) }]}\n/>`;\n\nlet counter = 0;\n\nconst AddImages: React.FC = () => {\n    const [slides, setSlides] = useState<CarouselSlide[]>([]);\n    const [lastAction, setLastAction] = useState<string>('Drag an image here, paste from clipboard, or click the add tile.');\n\n    const addFromFiles = useCallback((files: File[]) => {\n        const next = files.map<CarouselSlide>((file) => {\n            counter += 1;\n            return { id: `add-${counter}`, type: 'image', src: URL.createObjectURL(file), name: file.name || `image-${counter}` };\n        });\n        if (next.length === 0) return;\n        setSlides((prev) => [...prev, ...next]);\n        setLastAction(`Added ${next.length} image${next.length === 1 ? '' : 's'} (${next.map((s) => s.name).join(', ')}).`);\n    }, []);\n\n    const remove = useCallback((index: number) => {\n        setSlides((prev) => {\n            const target = prev[index];\n            if (target?.src?.startsWith('blob:')) URL.revokeObjectURL(target.src);\n            return prev.filter((_, i) => i !== index);\n        });\n        setLastAction(`Removed image at index ${index}.`);\n    }, []);\n\n    useEffect(() => {\n        const onPaste = (e: ClipboardEvent) => {\n            const files = Array.from(e.clipboardData?.files ?? []).filter((f) => f.type.startsWith('image/'));\n            if (files.length > 0) addFromFiles(files);\n        };\n        window.addEventListener('paste', onPaste);\n        return () => window.removeEventListener('paste', onPaste);\n    }, [addFromFiles]);\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Add Images (drop · paste · pick)\"\n                description=\"Set onAddImages to turn the carousel into an attachment surface: drag-and-drop onto the viewport, an add tile that opens the file picker, and (via a consumer paste listener) clipboard paste — all feeding the same callback.\"\n                centered={false}\n            >\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16 }}>\n                    <div className=\"w-full max-w-2xl mx-auto\">\n                        <Carousel\n                            slides={slides}\n                            navigation=\"thumbnails\"\n                            thumbnailPosition=\"bottom\"\n                            showThumbnailInfo\n                            aspectRatio=\"16/10\"\n                            onAddImages={addFromFiles}\n                            addImagesDropLabel=\"Drop image to attach\"\n                            thumbnailActions={[\n                                {\n                                    icon: <TrashIcon />,\n                                    label: 'Delete',\n                                    variant: 'danger',\n                                    onClick: (_slide, index) => remove(index),\n                                },\n                            ]}\n                        />\n                    </div>\n                    <div\n                        style={{\n                            padding: '12px 16px',\n                            background: 'var(--eui-bg-subtle)',\n                            border: '1px solid var(--eui-border-subtle)',\n                            borderRadius: 6,\n                            color: 'var(--eui-text)',\n                        }}\n                    >\n                        Last action: <strong>{lastAction}</strong>\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default AddImages;\n"
        },
        {
          "title": "Autoplay",
          "code": "import React from 'react';\nimport type { CarouselSlide } from '../../../components';\nimport { Carousel } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst slides: CarouselSlide[] = [\n    { id: 'a1', type: 'image', src: 'https://picsum.photos/seed/auto1/800/400', alt: 'Slide 1' },\n    { id: 'a2', type: 'image', src: 'https://picsum.photos/seed/auto2/800/400', alt: 'Slide 2' },\n    { id: 'a3', type: 'image', src: 'https://picsum.photos/seed/auto3/800/400', alt: 'Slide 3' },\n    { id: 'a4', type: 'image', src: 'https://picsum.photos/seed/auto4/800/400', alt: 'Slide 4' },\n];\n\nconst code = `import { Carousel } from 'fluxo-ui';\n\n<Carousel\n  slides={slides}\n  autoplay\n  autoplayInterval={3000}\n  loop\n/>`;\n\nconst Autoplay: React.FC = () => (\n    <>\n        <ComponentDemo\n            title=\"Autoplay with Loop\"\n            description=\"Slides advance automatically every 3 seconds and loop back to the first slide. Pauses on hover.\"\n            centered={false}\n        >\n            <div className=\"w-full max-w-2xl mx-auto\">\n                <Carousel slides={slides} autoplay autoplayInterval={3000} loop aspectRatio=\"16/9\" />\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default Autoplay;\n"
        },
        {
          "title": "BasicUsage",
          "code": "import React from 'react';\nimport type { CarouselSlide } from '../../../components';\nimport { Carousel } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst slides: CarouselSlide[] = [\n    { id: 's1', type: 'image', src: 'https://picsum.photos/seed/carousel1/800/400', alt: 'Mountain landscape' },\n    { id: 's2', type: 'image', src: 'https://picsum.photos/seed/carousel2/800/400', alt: 'Ocean sunset' },\n    { id: 's3', type: 'image', src: 'https://picsum.photos/seed/carousel3/800/400', alt: 'City skyline' },\n    { id: 's4', type: 'image', src: 'https://picsum.photos/seed/carousel4/800/400', alt: 'Forest trail' },\n    { id: 's5', type: 'image', src: 'https://picsum.photos/seed/carousel5/800/400', alt: 'Desert dunes' },\n];\n\nconst code = `import { Carousel } from 'fluxo-ui';\nimport type { CarouselSlide } from 'fluxo-ui';\n\nconst slides: CarouselSlide[] = [\n  { id: 's1', type: 'image', src: '/photo1.jpg', alt: 'Mountain landscape' },\n  { id: 's2', type: 'image', src: '/photo2.jpg', alt: 'Ocean sunset' },\n  { id: 's3', type: 'image', src: '/photo3.jpg', alt: 'City skyline' },\n];\n\n<Carousel slides={slides} />`;\n\nconst BasicUsage: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Image Carousel\" description=\"A basic image carousel with dot navigation and arrow buttons.\" centered={false}>\n            <div className=\"w-full max-w-2xl mx-auto\">\n                <Carousel slides={slides} aspectRatio=\"16/9\" />\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default BasicUsage;\n"
        },
        {
          "title": "EditableThumbnails",
          "code": "import React, { useState } from 'react';\nimport type { CarouselSlide } from '../../../components';\nimport { Carousel } from '../../../components';\nimport { EditIcon, PlusIcon, TrashIcon } from '../../../assets/icons';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst initialSlides: CarouselSlide[] = [\n    {\n        id: 'e1',\n        type: 'image',\n        src: 'https://picsum.photos/seed/edit1/800/500',\n        alt: 'Login screen',\n        thumbnail: 'https://picsum.photos/seed/edit1/120/80',\n        name: 'login',\n    },\n    {\n        id: 'e2',\n        type: 'image',\n        src: 'https://picsum.photos/seed/edit2/800/500',\n        alt: 'Dashboard',\n        thumbnail: 'https://picsum.photos/seed/edit2/120/80',\n        name: 'dashboard',\n    },\n    {\n        id: 'e3',\n        type: 'image',\n        src: 'https://picsum.photos/seed/edit3/800/500',\n        alt: 'Settings',\n        thumbnail: 'https://picsum.photos/seed/edit3/120/80',\n        name: 'settings',\n    },\n];\n\nconst code = `import { Carousel } from 'fluxo-ui';\nimport { EditIcon, PlusIcon, TrashIcon } from 'fluxo-ui/icons';\n\n<Carousel\n  slides={slides}\n  navigation=\"thumbnails\"\n  showThumbnailInfo\n  thumbnailActions={[\n    {\n      icon: <EditIcon />,\n      label: 'Rename',\n      onClick: (slide, index) => rename(index),\n    },\n    {\n      icon: <TrashIcon />,\n      label: 'Delete',\n      variant: 'danger',\n      onClick: (slide, index) => remove(index),\n    },\n  ]}\n  trailingThumbnail={{\n    icon: <PlusIcon />,\n    label: 'Add image',\n    onClick: () => addSlide(),\n  }}\n/>`;\n\nlet counter = initialSlides.length;\n\nconst EditableThumbnails: React.FC = () => {\n    const [slides, setSlides] = useState<CarouselSlide[]>(initialSlides);\n    const [lastAction, setLastAction] = useState<string>('No action yet — hover a thumbnail or click the + tile.');\n\n    const remove = (index: number) => {\n        setSlides((prev) => prev.filter((_, i) => i !== index));\n        setLastAction(`Deleted thumbnail at index ${index}.`);\n    };\n\n    const rename = (index: number) => {\n        setSlides((prev) =>\n            prev.map((slide, i) => (i === index ? { ...slide, name: `renamed-${index + 1}` } : slide)),\n        );\n        setLastAction(`Renamed thumbnail at index ${index}.`);\n    };\n\n    const addSlide = () => {\n        counter += 1;\n        const id = `e${counter}`;\n        setSlides((prev) => [\n            ...prev,\n            {\n                id,\n                type: 'image',\n                src: `https://picsum.photos/seed/${id}/800/500`,\n                alt: `New image ${counter}`,\n                thumbnail: `https://picsum.photos/seed/${id}/120/80`,\n                name: `image-${counter}`,\n            },\n        ]);\n        setLastAction(`Added a new thumbnail (${id}).`);\n    };\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Editable Thumbnails\"\n                description=\"Generic per-thumbnail action buttons plus a trailing add tile. Any icon and handler is configurable.\"\n                centered={false}\n            >\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16 }}>\n                    <div className=\"w-full max-w-2xl mx-auto\">\n                        <Carousel\n                            slides={slides}\n                            navigation=\"thumbnails\"\n                            thumbnailPosition=\"bottom\"\n                            showThumbnailInfo\n                            aspectRatio=\"16/10\"\n                            thumbnailActions={[\n                                {\n                                    icon: <EditIcon />,\n                                    label: 'Rename',\n                                    onClick: (_slide, index) => rename(index),\n                                },\n                                {\n                                    icon: <TrashIcon />,\n                                    label: 'Delete',\n                                    variant: 'danger',\n                                    onClick: (_slide, index) => remove(index),\n                                },\n                            ]}\n                            trailingThumbnail={{\n                                icon: <PlusIcon />,\n                                label: 'Add image',\n                                onClick: addSlide,\n                            }}\n                        />\n                    </div>\n                    <div\n                        style={{\n                            padding: '12px 16px',\n                            background: 'var(--eui-bg-subtle)',\n                            border: '1px solid var(--eui-border-subtle)',\n                            borderRadius: 6,\n                            color: 'var(--eui-text)',\n                        }}\n                    >\n                        Last action: <strong>{lastAction}</strong>\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default EditableThumbnails;\n"
        },
        {
          "title": "ThumbnailNav",
          "code": "import React from 'react';\nimport type { CarouselSlide } from '../../../components';\nimport { Carousel } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst slides: CarouselSlide[] = [\n    {\n        id: 't1',\n        type: 'image',\n        src: 'https://picsum.photos/seed/thumb1/800/500',\n        alt: 'Slide 1',\n        thumbnail: 'https://picsum.photos/seed/thumb1/120/80',\n    },\n    {\n        id: 't2',\n        type: 'image',\n        src: 'https://picsum.photos/seed/thumb2/800/500',\n        alt: 'Slide 2',\n        thumbnail: 'https://picsum.photos/seed/thumb2/120/80',\n    },\n    {\n        id: 't3',\n        type: 'image',\n        src: 'https://picsum.photos/seed/thumb3/800/500',\n        alt: 'Slide 3',\n        thumbnail: 'https://picsum.photos/seed/thumb3/120/80',\n    },\n    {\n        id: 't4',\n        type: 'image',\n        src: 'https://picsum.photos/seed/thumb4/800/500',\n        alt: 'Slide 4',\n        thumbnail: 'https://picsum.photos/seed/thumb4/120/80',\n    },\n    {\n        id: 't5',\n        type: 'image',\n        src: 'https://picsum.photos/seed/thumb5/800/500',\n        alt: 'Slide 5',\n        thumbnail: 'https://picsum.photos/seed/thumb5/120/80',\n    },\n    {\n        id: 't6',\n        type: 'image',\n        src: 'https://picsum.photos/seed/thumb6/800/500',\n        alt: 'Slide 6',\n        thumbnail: 'https://picsum.photos/seed/thumb6/120/80',\n    },\n];\n\nconst code = `import { Carousel } from 'fluxo-ui';\n\n<Carousel\n  slides={slides}\n  navigation=\"thumbnails\"\n  thumbnailPosition=\"bottom\"\n/>`;\n\nconst ThumbnailNav: React.FC = () => (\n    <>\n        <ComponentDemo\n            title=\"Thumbnail Navigation\"\n            description=\"Navigate slides using clickable thumbnail strip below the main viewport.\"\n            centered={false}\n        >\n            <div className=\"w-full max-w-2xl mx-auto\">\n                <Carousel slides={slides} navigation=\"thumbnails\" thumbnailPosition=\"bottom\" aspectRatio=\"16/10\" />\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default ThumbnailNav;\n"
        }
      ],
      "props": {
        "carouselProps": {
          "slides": {
            "type": "CarouselSlide[]",
            "required": true,
            "description": "Array of slide data."
          },
          "activeIndex": {
            "type": "number",
            "description": "Controlled active slide index."
          },
          "onSlideChange": {
            "type": "(index: number) => void",
            "description": "Called when the active slide changes."
          },
          "navigation": {
            "type": "'dots' | 'arrows' | 'thumbnails' | 'none'",
            "default": "'dots'",
            "description": "Navigation style."
          },
          "thumbnailPosition": {
            "type": "'top' | 'bottom' | 'left' | 'right'",
            "default": "'bottom'",
            "description": "Position of thumbnail strip."
          },
          "autoplay": {
            "type": "boolean",
            "default": "false",
            "description": "Enable automatic slide advancement."
          },
          "autoplayInterval": {
            "type": "number",
            "default": "5000",
            "description": "Autoplay interval in milliseconds."
          },
          "loop": {
            "type": "boolean",
            "default": "false",
            "description": "Loop back to first slide after the last."
          },
          "showArrows": {
            "type": "boolean",
            "default": "true",
            "description": "Show previous/next arrow buttons."
          },
          "showDots": {
            "type": "boolean",
            "description": "Show dot indicators (overrides navigation)."
          },
          "lazyLoad": {
            "type": "boolean",
            "default": "false",
            "description": "Lazy-load images as they become active."
          },
          "swipeable": {
            "type": "boolean",
            "default": "true",
            "description": "Enable swipe/drag gesture navigation."
          },
          "aspectRatio": {
            "type": "string",
            "description": "CSS aspect ratio for slides (e.g. \"16/9\")."
          },
          "className": {
            "type": "string",
            "description": "Additional CSS class for the container."
          },
          "slideClassName": {
            "type": "string",
            "description": "Additional CSS class for each slide."
          },
          "ariaLabel": {
            "type": "string",
            "default": "'Image carousel'",
            "description": "Accessible name for the carousel region."
          },
          "showAutoplayToggle": {
            "type": "boolean",
            "default": "true",
            "description": "Show a play/pause button when autoplay is enabled (WCAG 2.2.2)."
          },
          "thumbnailActions": {
            "type": "CarouselThumbnailAction[]",
            "description": "Per-thumbnail overlay action buttons (e.g. delete, edit). Each action has { icon, label, onClick(slide, index), variant?, isVisible? }. Generic — any icon and handler."
          },
          "trailingThumbnail": {
            "type": "CarouselTrailingThumbnail",
            "description": "An extra tile rendered after the last thumbnail (e.g. an add button). Shape: { icon, label, onClick }."
          },
          "onAddImages": {
            "type": "(files: File[]) => void",
            "description": "Enables image attachment. When set, the carousel accepts drag-and-drop of image files onto the viewport (with a drop overlay) and renders a trailing 'add' tile that opens a file picker (unless a custom trailingThumbnail is provided). Receives the filtered File[]. Combine with a consumer-side clipboard paste handler that forwards pasted files to the same callback."
          },
          "addImagesAccept": {
            "type": "string",
            "default": "'image/*'",
            "description": "Comma-separated accept filter (MIME types like 'image/png' or extensions like '.png') applied to dropped and picked files before onAddImages fires."
          },
          "addImagesDropLabel": {
            "type": "string",
            "default": "'Drop image to add'",
            "description": "Label shown in the drop overlay and used as the trailing add tile's accessible label when onAddImages is set."
          }
        },
        "thumbnailActionProps": {
          "icon": {
            "type": "ReactNode",
            "required": true,
            "description": "Icon rendered inside the action button."
          },
          "label": {
            "type": "string",
            "required": true,
            "description": "Accessible label / tooltip for the action."
          },
          "onClick": {
            "type": "(slide: CarouselSlide, index: number) => void",
            "required": true,
            "description": "Invoked with the slide and its index when the action is clicked."
          },
          "variant": {
            "type": "'default' | 'danger'",
            "default": "'default'",
            "description": "Visual style of the action button."
          },
          "isVisible": {
            "type": "(slide: CarouselSlide, index: number) => boolean",
            "description": "Optional predicate to conditionally show the action per slide."
          }
        },
        "trailingThumbnailProps": {
          "icon": {
            "type": "ReactNode",
            "required": true,
            "description": "Icon rendered inside the trailing tile (e.g. a plus icon)."
          },
          "label": {
            "type": "string",
            "required": true,
            "description": "Accessible label / tooltip for the trailing tile."
          },
          "onClick": {
            "type": "() => void",
            "required": true,
            "description": "Invoked when the trailing tile is clicked."
          }
        },
        "slideProps": {
          "id": {
            "type": "string",
            "required": true,
            "description": "Unique identifier for the slide."
          },
          "type": {
            "type": "'image' | 'video' | 'custom'",
            "required": true,
            "description": "Slide content type."
          },
          "src": {
            "type": "string",
            "description": "Image URL (for image type)."
          },
          "alt": {
            "type": "string",
            "description": "Alt text for the image."
          },
          "thumbnail": {
            "type": "string",
            "description": "Thumbnail URL for thumbnail navigation."
          },
          "content": {
            "type": "ReactNode",
            "description": "Custom content (for custom type)."
          }
        }
      },
      "storyDir": "carousel"
    },
    "ChatConversations": {
      "name": "ChatConversations",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {
        "chatConversationsProps": {
          "conversations": {
            "type": "ChatConversationItem[]",
            "required": true,
            "description": "List of conversations to render in the sidebar."
          },
          "activeId": {
            "type": "string",
            "description": "ID of the currently active conversation; highlighted in the list."
          },
          "onSelect": {
            "type": "(id: string) => void",
            "description": "Fires when a conversation row is clicked."
          },
          "onSearch": {
            "type": "(query: string) => void",
            "description": "Fires when the search input changes. Internal filtering still runs in addition to this."
          },
          "onPin": {
            "type": "(id: string, pinned: boolean) => void",
            "description": "Fires when an item is pinned/unpinned (consumer-triggered actions)."
          },
          "onArchive": {
            "type": "(id: string, archived: boolean) => void",
            "description": "Fires when an item is archived/unarchived."
          },
          "onDelete": {
            "type": "(id: string) => void",
            "description": "Fires when an item is deleted."
          },
          "searchable": {
            "type": "boolean",
            "default": "true",
            "description": "Show the built-in search input above the list."
          },
          "sidebarWidth": {
            "type": "number | string",
            "default": "'280px'",
            "description": "Initial width of the sidebar panel."
          },
          "minSidebarWidth": {
            "type": "number",
            "default": "200",
            "description": "Minimum sidebar panel width."
          },
          "maxSidebarWidth": {
            "type": "number",
            "default": "480",
            "description": "Maximum sidebar panel width."
          },
          "hideArchived": {
            "type": "boolean",
            "description": "Filter archived conversations out of the visible list."
          },
          "emptyState": {
            "type": "ReactNode",
            "description": "Content rendered when no conversations match."
          },
          "renderItem": {
            "type": "(item: ChatConversationItem, ctx) => ReactNode",
            "description": "Custom row renderer."
          },
          "children": {
            "type": "ReactNode",
            "description": "Right-side content. Typically a <ChatWindow /> for the active conversation."
          },
          "className": {
            "type": "string",
            "description": "Extra class on the root container."
          },
          "style": {
            "type": "CSSProperties",
            "description": "Extra inline styles on the root container."
          },
          "placeholder": {
            "type": "string",
            "default": "'Search conversations…'",
            "description": "Search input placeholder."
          },
          "title": {
            "type": "ReactNode",
            "description": "Optional title shown above the search input."
          }
        }
      }
    },
    "ChatLauncher": {
      "name": "ChatLauncher",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {
        "chatLauncherProps": {
          "variant": {
            "type": "'icon' | 'morph' | 'beacon' | 'pulsar' | 'expand' | 'bar' | 'spark'",
            "default": "'spark'",
            "description": "Visual style for the launcher button."
          },
          "imageUrl": {
            "type": "string",
            "description": "Logo image rendered inside the launcher. Falls back to default chat icon if not set."
          },
          "text": {
            "type": "string",
            "default": "'Live Chat'",
            "description": "Label for variants that show text (bar, beacon, expand, spark)."
          },
          "bgColor": {
            "type": "string",
            "description": "Primary background color."
          },
          "secBgColor": {
            "type": "string",
            "description": "Secondary color used in gradients."
          },
          "fontColor": {
            "type": "string",
            "description": "Foreground (icon/text) color."
          },
          "align": {
            "type": "'bottomRight' | 'bottomLeft'",
            "default": "'bottomRight'",
            "description": "Side of the screen the launcher is anchored to."
          },
          "spacingCorner": {
            "type": "string",
            "description": "Distance from the anchored side edge."
          },
          "spacingBottom": {
            "type": "string",
            "description": "Distance from the bottom edge."
          },
          "showTooltip": {
            "type": "boolean",
            "description": "Show an idle tooltip near the launcher."
          },
          "tooltipText": {
            "type": "string",
            "default": "'We are online!'",
            "description": "Tooltip text."
          },
          "icon": {
            "type": "ReactNode",
            "description": "Custom icon overriding the default chat icon."
          },
          "className": {
            "type": "string",
            "description": "Extra class on the root."
          },
          "style": {
            "type": "CSSProperties",
            "description": "Extra inline styles."
          },
          "buttonOnMobile": {
            "type": "boolean",
            "description": "Force the simple icon variant on mobile when variant is bar/expand."
          },
          "autoAnimate": {
            "type": "boolean",
            "default": "true",
            "description": "Enable periodic animations on variants that support them (e.g., expand)."
          },
          "onClick": {
            "type": "() => void",
            "required": true,
            "description": "Click handler — toggles open/close state externally."
          }
        }
      }
    },
    "ChatWindow": {
      "name": "ChatWindow",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {
        "chatWindowProps": {
          "messages": {
            "type": "ChatMessage[]",
            "required": true,
            "description": "Controlled messages array. Consumer is fully responsible for maintaining and mutating this list."
          },
          "onSendMessage": {
            "type": "(data: ChatSendPayload) => void",
            "description": "Fired when the user sends a message via the composer. Includes text, attachments, and inReplyTo when relevant."
          },
          "onUserAction": {
            "type": "(event: UserActionEvent) => void",
            "description": "Generic callback for in-message user actions (option click, custom plugin actions, etc.)."
          },
          "composerText": {
            "type": "string",
            "description": "Controlled composer value. If undefined, the component manages composer state internally."
          },
          "onComposerTextChange": {
            "type": "(text: string) => void",
            "description": "Fires whenever composer text changes (typing, emoji insert, shortcode replacement)."
          },
          "composerPlaceholder": {
            "type": "string",
            "default": "'Type your message...'",
            "description": "Placeholder shown in the composer textarea."
          },
          "composerDisabled": {
            "type": "boolean",
            "description": "Disables the composer."
          },
          "renderComposer": {
            "type": "(ctx: ComposerCtx) => ReactNode",
            "description": "Replaces the entire composer with a custom render. Built-in actions are skipped."
          },
          "showSendButton": {
            "type": "boolean",
            "default": "true",
            "description": "Show the send button in the composer."
          },
          "sendOnEnter": {
            "type": "boolean",
            "default": "true",
            "description": "Send when Enter is pressed (Shift+Enter inserts newline)."
          },
          "showMic": {
            "type": "boolean",
            "description": "Show the mic button. Defaults to true if onMicClick is set."
          },
          "onMicClick": {
            "type": "() => void",
            "description": "Callback when the mic button is clicked. Voice handling is delegated entirely to the consumer."
          },
          "isMicActive": {
            "type": "boolean",
            "description": "When true, the mic button shows a pulsing animation."
          },
          "emoji": {
            "type": "EmojiConfig",
            "description": "Enable + configure the emoji picker, categories, custom emojis, and shortcode replacement."
          },
          "attachments": {
            "type": "AttachmentDisplayConfig",
            "description": "Enable + configure attachments: file types, max files, max size, display mode in completed messages, onAttach callback."
          },
          "header": {
            "type": "ChatHeaderConfig",
            "description": "Header config: title, subtitle, logo, colors, button visibility flags, menu items."
          },
          "renderHeader": {
            "type": "(ctx: HeaderCtx) => ReactNode",
            "description": "Replace the entire header with a custom render."
          },
          "icons": {
            "type": "ChatIcons",
            "description": "Override every built-in icon (minimize, close, restart, menu, send, mic, attach, emoji, bot, user, status icons)."
          },
          "tooltips": {
            "type": "ChatTooltips",
            "description": "Tooltip text for every built-in icon button."
          },
          "onMinimize": {
            "type": "() => boolean | Promise<boolean>",
            "description": "Fires when minimize is clicked. Return false to cancel."
          },
          "onClose": {
            "type": "() => boolean | Promise<boolean>",
            "description": "Fires when close is clicked. Return false to cancel. Consumer is expected to unmount."
          },
          "onRestart": {
            "type": "() => boolean | Promise<boolean>",
            "description": "Fires when restart is clicked. Return false to cancel."
          },
          "isMinimized": {
            "type": "boolean",
            "description": "Controlled minimized state. When true, the window does not render."
          },
          "headerSlot": {
            "type": "ReactNode",
            "description": "Custom content rendered between the header and message body."
          },
          "aboveComposerSlot": {
            "type": "ReactNode",
            "description": "Custom content rendered above the composer (suggestion chips, etc.)."
          },
          "belowComposerSlot": {
            "type": "ReactNode",
            "description": "Custom content rendered below the composer (disclaimer, branding)."
          },
          "showTime": {
            "type": "boolean",
            "description": "Show time under each message."
          },
          "showAvatars": {
            "type": "boolean",
            "default": "true",
            "description": "Show avatar circles next to messages."
          },
          "customMessageTypes": {
            "type": "Record<string, ComponentType>",
            "description": "Plug-in custom message renderers keyed by type. Merged into the built-in template map."
          },
          "messageActions": {
            "type": "MessageActionsConfig",
            "description": "Per-message action bar shown on hover/long-press. Consumer-driven items array."
          },
          "reactions": {
            "type": "ReactionsConfig",
            "description": "Emoji reactions on messages. Consumer maintains reactions on each message and gets onReact."
          },
          "feedback": {
            "type": "FeedbackConfig",
            "description": "Thumbs up/down feedback on assistant messages. Optional askForComment flag."
          },
          "reply": {
            "type": "ReplyConfig",
            "description": "Enable replies. Style: pinned (chip in composer only), quoted (embedded in new message), both."
          },
          "typingUsers": {
            "type": "TypingUser[]",
            "description": "List of users currently typing. Empty / undefined hides indicator."
          },
          "showLoader": {
            "type": "boolean",
            "description": "Force-show the typing dots loader (legacy single-bot mode)."
          },
          "onRetryMessage": {
            "type": "(messageId: string) => void",
            "description": "Fires when the user clicks the failed-status icon to retry."
          },
          "draggable": {
            "type": "boolean",
            "description": "Enable dragging the window by the header. Disabled on mobile."
          },
          "resizable": {
            "type": "boolean",
            "description": "Enable resizing from any edge or corner. Disabled on mobile."
          },
          "persist": {
            "type": "boolean | 'session'",
            "description": "true uses localStorage, 'session' uses sessionStorage, false/undefined disables persistence."
          },
          "persistKey": {
            "type": "string",
            "default": "'fluxo-chat-window'",
            "description": "Storage key for persisted position and size."
          },
          "defaultPosition": {
            "type": "{ x?: number; y?: number }",
            "description": "Initial drag offset (only applies when draggable)."
          },
          "defaultSize": {
            "type": "{ width?: number; height?: number }",
            "description": "Initial size in pixels (only applies when resizable)."
          },
          "minWidth": {
            "type": "number",
            "default": "320",
            "description": "Minimum window width in pixels."
          },
          "minHeight": {
            "type": "number",
            "default": "420",
            "description": "Minimum window height in pixels."
          },
          "maxWidth": {
            "type": "number | string",
            "default": "'95vw'",
            "description": "Maximum window width."
          },
          "maxHeight": {
            "type": "number | string",
            "default": "'95vh'",
            "description": "Maximum window height."
          },
          "theme": {
            "type": "ChatTheme",
            "default": "'classic'",
            "description": "Visual theme: classic, modern, iris, dusk, mist, ember, canvas, prism, aurora."
          },
          "colorMode": {
            "type": "'light' | 'dark' | 'auto'",
            "description": "Force light or dark mode. Auto follows OS / theme defaults."
          },
          "cssVars": {
            "type": "Record<string, string>",
            "description": "Override --euic-* CSS variables for primary, fonts, surfaces, etc."
          },
          "className": {
            "type": "string",
            "description": "Extra class on the root container."
          },
          "style": {
            "type": "CSSProperties",
            "description": "Extra inline styles on the root container."
          },
          "align": {
            "type": "'bottomRight' | 'bottomLeft'",
            "default": "'bottomRight'",
            "description": "Anchor side when not draggable."
          },
          "spacingCorner": {
            "type": "string",
            "default": "'5px'",
            "description": "Distance from the anchored corner edge."
          },
          "spacingBottom": {
            "type": "string",
            "default": "'5px'",
            "description": "Distance from the anchored bottom edge."
          },
          "ariaLabel": {
            "type": "string",
            "default": "'Chat'",
            "description": "ARIA label for the window dialog."
          },
          "announcements": {
            "type": "boolean",
            "default": "true",
            "description": "Live-region announcements for new assistant messages."
          },
          "trapFocus": {
            "type": "boolean",
            "description": "Trap focus inside the window. Defaults to true in fullscreen mode."
          },
          "shortcutsHelp": {
            "type": "boolean",
            "default": "true",
            "description": "Enable Ctrl+/ shortcuts help dialog."
          },
          "fullscreen": {
            "type": "boolean",
            "description": "Render the window full-viewport."
          },
          "noShadow": {
            "type": "boolean",
            "description": "Remove window shadow."
          },
          "noAnimation": {
            "type": "boolean",
            "description": "Disable open/close animations."
          },
          "fontFamily": {
            "type": "string",
            "description": "Override the body font family."
          },
          "width": {
            "type": "number | string",
            "description": "Explicit width when not resizable."
          },
          "height": {
            "type": "number | string",
            "description": "Explicit height when not resizable."
          }
        }
      }
    },
    "CollapsiblePanel": {
      "name": "CollapsiblePanel",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "AccordionGroup",
          "code": "import React from 'react';\nimport { CollapsiblePanel, CollapsiblePanelGroup } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { CollapsiblePanel, CollapsiblePanelGroup } from 'fluxo-ui';\n\n<CollapsiblePanelGroup accordion variant=\"bordered\">\n  <CollapsiblePanel id=\"faq-1\" title=\"What is CollapsiblePanel?\">\n    <p>A flexible panel that expands and collapses.</p>\n  </CollapsiblePanel>\n  <CollapsiblePanel id=\"faq-2\" title=\"Does it support accordion mode?\">\n    <p>Yes! Wrap panels in a Group with accordion prop.</p>\n  </CollapsiblePanel>\n</CollapsiblePanelGroup>`;\n\nconst AccordionGroup: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Accordion Group\" centered={false}>\n            <div className=\"w-full\">\n                <CollapsiblePanelGroup accordion variant=\"bordered\" defaultOpenKeys={['acc-faq-1']}>\n                    <CollapsiblePanel id=\"acc-faq-1\" title=\"What is CollapsiblePanel?\">\n                        <p className=\"text-sm leading-relaxed\">\n                            A flexible, accessible component for expanding and collapsing content sections. Supports multiple variants,\n                            sizes, icons, and group/accordion behavior.\n                        </p>\n                    </CollapsiblePanel>\n                    <CollapsiblePanel id=\"acc-faq-2\" title=\"Does it support accordion mode?\">\n                        <p className=\"text-sm leading-relaxed\">\n                            Yes! Wrap multiple panels in a <code className=\"font-mono text-xs\">CollapsiblePanelGroup</code> with the{' '}\n                            <code className=\"font-mono text-xs\">accordion</code> prop. Only one panel can be open at a time.\n                        </p>\n                    </CollapsiblePanel>\n                    <CollapsiblePanel id=\"acc-faq-3\" title=\"Can I control which panels are open?\">\n                        <p className=\"text-sm leading-relaxed\">\n                            Use <code className=\"font-mono text-xs\">defaultOpenKeys</code> for initial state, or the individual{' '}\n                            <code className=\"font-mono text-xs\">open</code> and <code className=\"font-mono text-xs\">onToggle</code> props\n                            for full controlled behavior.\n                        </p>\n                    </CollapsiblePanel>\n                    <CollapsiblePanel id=\"acc-faq-4\" title=\"Is it keyboard accessible?\">\n                        <p className=\"text-sm leading-relaxed\">\n                            Fully ADA-compliant. Headers are focusable, respond to Enter and Space, use proper ARIA attributes (\n                            <code className=\"font-mono text-xs\">aria-expanded</code>,\n                            <code className=\"font-mono text-xs\">aria-controls</code>,{' '}\n                            <code className=\"font-mono text-xs\">role=\"region\"</code>), and respect{' '}\n                            <code className=\"font-mono text-xs\">prefers-reduced-motion</code>.\n                        </p>\n                    </CollapsiblePanel>\n                </CollapsiblePanelGroup>\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} />\n        </div>\n    </>\n);\n\nexport default AccordionGroup;\n"
        },
        {
          "title": "BasicUsage",
          "code": "import React from 'react';\nimport { CollapsiblePanel } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { CollapsiblePanel } from 'fluxo-ui';\n\n<CollapsiblePanel title=\"Getting Started\" defaultOpen>\n  <p>Welcome to the CollapsiblePanel component! Click the header to toggle.</p>\n</CollapsiblePanel>\n\n<CollapsiblePanel title=\"Advanced Features\" subtitle=\"Explore more options\">\n  <p>This panel has a subtitle and starts collapsed.</p>\n</CollapsiblePanel>`;\n\nconst BasicUsage: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Basic Usage\" centered={false}>\n            <div className=\"space-y-3 w-full\">\n                <CollapsiblePanel title=\"Getting Started\" defaultOpen>\n                    <p className=\"text-sm leading-relaxed\">\n                        Welcome to the CollapsiblePanel component. Click the header to expand or collapse the content area with a smooth\n                        height animation. This panel starts open by default.\n                    </p>\n                </CollapsiblePanel>\n                <CollapsiblePanel title=\"Advanced Features\" subtitle=\"Explore the full set of options available\">\n                    <p className=\"text-sm leading-relaxed\">\n                        Panels support subtitles, icons, custom header actions, multiple variants, sizes, and full keyboard accessibility.\n                        They can be used standalone or grouped in an accordion.\n                    </p>\n                </CollapsiblePanel>\n                <CollapsiblePanel title=\"Performance & Lazy Rendering\">\n                    <p className=\"text-sm leading-relaxed\">\n                        Use the <code className=\"font-mono text-xs\">lazy</code> prop to defer rendering of content until the panel is first\n                        opened, or <code className=\"font-mono text-xs\">destroyOnCollapse</code> to unmount content when collapsed.\n                    </p>\n                </CollapsiblePanel>\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} />\n        </div>\n    </>\n);\n\nexport default BasicUsage;\n"
        },
        {
          "title": "Controlled",
          "code": "import React, { useState } from 'react';\nimport { Button, CollapsiblePanel } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `const [isOpen, setIsOpen] = useState(false);\n\n<Button onClick={() => setIsOpen(!isOpen)}>\n  {isOpen ? 'Collapse' : 'Expand'}\n</Button>\n\n<CollapsiblePanel\n  title=\"Controlled Panel\"\n  open={isOpen}\n  onToggle={setIsOpen}\n>\n  <p>Externally controlled open state.</p>\n</CollapsiblePanel>`;\n\nconst Controlled: React.FC = () => {\n    const [isOpen, setIsOpen] = useState(true);\n\n    return (\n        <>\n            <ComponentDemo title=\"Controlled Mode\" centered={false}>\n                <div className=\"space-y-3 w-full\">\n                    <div className=\"flex gap-2\">\n                        <Button size=\"sm\" onClick={() => setIsOpen(!isOpen)}>\n                            {isOpen ? 'Collapse' : 'Expand'}\n                        </Button>\n                    </div>\n                    <CollapsiblePanel\n                        title=\"Controlled Panel\"\n                        subtitle=\"Open state is managed externally\"\n                        variant=\"elevated\"\n                        open={isOpen}\n                        onToggle={setIsOpen}\n                    >\n                        <p className=\"text-sm leading-relaxed\">\n                            This panel is fully controlled — the <code className=\"font-mono text-xs\">open</code> prop determines\n                            whether it is expanded, and <code className=\"font-mono text-xs\">onToggle</code> reports the requested\n                            state change. You can still click the header to toggle, or use the external button above.\n                        </p>\n                    </CollapsiblePanel>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default Controlled;\n"
        },
        {
          "title": "CustomHeaderTemplate",
          "code": "import React from 'react';\nimport { CollapsiblePanel } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<CollapsiblePanel\n  title=\"Custom Header\"\n  headerTemplate={({ isOpen, toggle }) => (\n    <div className=\"custom-header\" onClick={toggle}>\n      <span>{isOpen ? '▼' : '▶'}</span>\n      <span>My Custom Header</span>\n    </div>\n  )}\n>\n  ...\n</CollapsiblePanel>`;\n\nconst CustomHeaderTemplate: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Custom Header Template\" centered={false}>\n            <div className=\"space-y-3 w-full\">\n                <CollapsiblePanel\n                    title=\"Custom Header\"\n                    variant=\"ghost\"\n                    defaultOpen\n                    headerTemplate={({ isOpen, toggle }) => (\n                        <div\n                            className=\"flex items-center gap-3 p-3 rounded-lg cursor-pointer\"\n                            style={{\n                                background: isOpen\n                                    ? 'linear-gradient(135deg, var(--eui-primary-subtle), transparent)'\n                                    : 'transparent',\n                                borderLeft: `3px solid ${isOpen ? 'var(--eui-primary)' : 'transparent'}`,\n                                transition: 'all 0.3s ease',\n                            }}\n                            onClick={toggle}\n                        >\n                            <span\n                                style={{\n                                    display: 'inline-flex',\n                                    alignItems: 'center',\n                                    justifyContent: 'center',\n                                    width: 32,\n                                    height: 32,\n                                    borderRadius: '50%',\n                                    backgroundColor: 'var(--eui-primary)',\n                                    color: 'var(--eui-text-on-primary)',\n                                    fontSize: 14,\n                                    fontWeight: 600,\n                                }}\n                            >\n                                1\n                            </span>\n                            <div className=\"flex-1\">\n                                <div className=\"font-semibold text-sm\" style={{ color: 'var(--eui-text)' }}>Step 1: Project Setup</div>\n                                <div className=\"text-xs\" style={{ color: 'var(--eui-text-muted)' }}>Initialize repository and install dependencies</div>\n                            </div>\n                            <svg\n                                style={{\n                                    width: 16, height: 16,\n                                    transform: isOpen ? 'rotate(180deg)' : 'rotate(0)',\n                                    transition: 'transform 0.3s cubic-bezier(0.4,0,0.2,1)',\n                                    color: 'var(--eui-text-muted)',\n                                }}\n                                viewBox=\"0 0 20 20\" fill=\"currentColor\"\n                            >\n                                <path fillRule=\"evenodd\" d=\"M5.22 8.22a.75.75 0 0 1 1.06 0L10 11.94l3.72-3.72a.75.75 0 1 1 1.06 1.06l-4.25 4.25a.75.75 0 0 1-1.06 0L5.22 9.28a.75.75 0 0 1 0-1.06Z\" clipRule=\"evenodd\" />\n                            </svg>\n                        </div>\n                    )}\n                >\n                    <div className=\"p-3 text-sm leading-relaxed\">\n                        The <code className=\"font-mono text-xs\">headerTemplate</code> prop gives you full control over the\n                        header rendering. You receive <code className=\"font-mono text-xs\">isOpen</code> and\n                        <code className=\"font-mono text-xs\">toggle</code> and can build any custom UI. The toggle indicator,\n                        title, subtitle, and icon props are all ignored when a template is provided.\n                    </div>\n                </CollapsiblePanel>\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} />\n        </div>\n    </>\n);\n\nexport default CustomHeaderTemplate;\n"
        },
        {
          "title": "DisabledState",
          "code": "import React from 'react';\nimport { CollapsiblePanel } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<CollapsiblePanel title=\"Locked Section\" disabled>\n  <p>This content is not accessible.</p>\n</CollapsiblePanel>\n\n<CollapsiblePanel title=\"Locked But Open\" disabled defaultOpen>\n  <p>Content is visible but cannot be collapsed.</p>\n</CollapsiblePanel>`;\n\nconst DisabledState: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Disabled State\" centered={false}>\n            <div className=\"space-y-3 w-full\">\n                <CollapsiblePanel title=\"Locked Section\" subtitle=\"Cannot be toggled\" disabled variant=\"bordered\">\n                    <p className=\"text-sm leading-relaxed\">\n                        This content is not accessible because the panel is disabled and collapsed.\n                    </p>\n                </CollapsiblePanel>\n                <CollapsiblePanel title=\"Locked But Open\" subtitle=\"Visible but cannot be collapsed\" disabled defaultOpen variant=\"bordered\">\n                    <p className=\"text-sm leading-relaxed\">\n                        This panel starts open and is disabled — the user can see the content but cannot collapse it.\n                        The header cursor changes to <code className=\"font-mono text-xs\">not-allowed</code> and the hover effect is suppressed.\n                    </p>\n                </CollapsiblePanel>\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} />\n        </div>\n    </>\n);\n\nexport default DisabledState;\n"
        },
        {
          "title": "HeaderActions",
          "code": "import React, { useState } from 'react';\nimport { Button, CollapsiblePanel } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<CollapsiblePanel\n  title=\"Notifications\"\n  headerActions={<Button size=\"xs\" onClick={handleClear}>Clear All</Button>}\n>\n  ...\n</CollapsiblePanel>`;\n\nconst HeaderActions: React.FC = () => {\n    const [count, setCount] = useState(5);\n\n    return (\n        <>\n            <ComponentDemo title=\"Header Actions\" centered={false}>\n                <div className=\"space-y-3 w-full\">\n                    <CollapsiblePanel\n                        title=\"Notifications\"\n                        subtitle={`${count} unread`}\n                        variant=\"bordered\"\n                        defaultOpen\n                        headerActions={\n                            <Button size=\"xs\" layout=\"outlined\" onClick={() => setCount(0)}>\n                                Clear All\n                            </Button>\n                        }\n                    >\n                        <p className=\"text-sm leading-relaxed\">\n                            Header actions sit at the trailing edge of the header, next to the toggle indicator.\n                            Clicking them does not toggle the panel — event propagation is stopped automatically.\n                        </p>\n                    </CollapsiblePanel>\n                    <CollapsiblePanel\n                        title=\"Deployment Logs\"\n                        variant=\"separated\"\n                        headerActions={\n                            <div className=\"flex gap-2\">\n                                <Button size=\"xs\" layout=\"plain\">Refresh</Button>\n                                <Button size=\"xs\" layout=\"outlined\">Download</Button>\n                            </div>\n                        }\n                    >\n                        <p className=\"text-sm leading-relaxed\">\n                            You can place any interactive element in the header actions slot — buttons, badges, switches, or custom controls.\n                        </p>\n                    </CollapsiblePanel>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default HeaderActions;\n"
        },
        {
          "title": "HorizontalTabs",
          "code": "import React from 'react';\nimport type { CollapsibleTabItem } from '../../../components';\nimport { CollapsibleTabs } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { CollapsibleTabs } from 'fluxo-ui';\n\nconst tabs = [\n  { id: 'editor', label: 'Editor', isOpen: true, render: () => <div>Editor</div> },\n  { id: 'preview', label: 'Preview', isOpen: true, render: () => <div>Preview</div> },\n  { id: 'console', label: 'Console', isOpen: false, render: () => <div>Console</div> },\n];\n\n<CollapsibleTabs tabs={tabs} height={400} />`;\n\nconst tabs: CollapsibleTabItem[] = [\n    {\n        id: 'editor',\n        label: 'Editor',\n        isOpen: true,\n        render: () => (\n            <div className=\"p-4 h-full\">\n                <h3 className=\"font-semibold mb-2\">Code Editor</h3>\n                <div className=\"font-mono text-xs leading-relaxed opacity-70\">\n                    <div>{'function greet(name: string) {'}</div>\n                    <div>{'  return `Hello, ${name}!`;'}</div>\n                    <div>{'}'}</div>\n                    <div className=\"mt-2\">{'const message = greet(\"World\");'}</div>\n                    <div>{'console.log(message);'}</div>\n                </div>\n            </div>\n        ),\n    },\n    {\n        id: 'preview',\n        label: 'Preview',\n        isOpen: true,\n        render: () => (\n            <div className=\"p-4 h-full\">\n                <h3 className=\"font-semibold mb-2\">Live Preview</h3>\n                <div className=\"text-sm opacity-70\">\n                    <p>Hello, World!</p>\n                </div>\n            </div>\n        ),\n    },\n    {\n        id: 'console',\n        label: 'Console',\n        isOpen: false,\n        render: () => (\n            <div className=\"p-4 h-full\">\n                <h3 className=\"font-semibold mb-2\">Console Output</h3>\n                <div className=\"font-mono text-xs opacity-60\">\n                    <div>[INFO] Compiled successfully</div>\n                    <div>[LOG] Hello, World!</div>\n                </div>\n            </div>\n        ),\n    },\n];\n\nconst HorizontalTabs: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Horizontal Collapsible Tabs\" centered={false}>\n            <div className=\"w-full\" style={{ height: 300 }}>\n                <CollapsibleTabs tabs={tabs} height={300} />\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} />\n        </div>\n    </>\n);\n\nexport default HorizontalTabs;\n"
        },
        {
          "title": "HorizontalTabsVariants",
          "code": "import React from 'react';\nimport { CollapsibleTabs } from '../../../components';\nimport type { CollapsibleTabItem, CollapsibleTabsVariant } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<CollapsibleTabs tabs={tabs} variant=\"bordered\" />\n<CollapsibleTabs tabs={tabs} variant=\"elevated\" />`;\n\nconst makeTabs = (prefix: string): CollapsibleTabItem[] => [\n    {\n        id: `${prefix}-panel-a`,\n        label: 'Panel A',\n        isOpen: true,\n        render: () => (\n            <div className=\"p-4 h-full\">\n                <h3 className=\"font-semibold mb-1 text-sm\">Panel A</h3>\n                <p className=\"text-xs opacity-70\">First panel content with full data view.</p>\n            </div>\n        ),\n    },\n    {\n        id: `${prefix}-panel-b`,\n        label: 'Panel B',\n        isOpen: true,\n        render: () => (\n            <div className=\"p-4 h-full\">\n                <h3 className=\"font-semibold mb-1 text-sm\">Panel B</h3>\n                <p className=\"text-xs opacity-70\">Second panel content with details.</p>\n            </div>\n        ),\n    },\n    {\n        id: `${prefix}-panel-c`,\n        label: 'Panel C',\n        isOpen: false,\n        render: () => (\n            <div className=\"p-4 h-full\">\n                <h3 className=\"font-semibold mb-1 text-sm\">Panel C</h3>\n                <p className=\"text-xs opacity-70\">Third panel, collapsed by default.</p>\n            </div>\n        ),\n    },\n];\n\nconst variants: CollapsibleTabsVariant[] = ['default', 'bordered', 'elevated'];\n\nconst HorizontalTabsVariants: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Horizontal Tabs Variants\" centered={false}>\n            <div className=\"space-y-6 w-full\">\n                {variants.map((v) => (\n                    <div key={v}>\n                        <p className=\"text-sm font-medium mb-2 capitalize\">{v}</p>\n                        <div style={{ height: 180 }}>\n                            <CollapsibleTabs tabs={makeTabs(v)} variant={v} height={180} />\n                        </div>\n                    </div>\n                ))}\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} />\n        </div>\n    </>\n);\n\nexport default HorizontalTabsVariants;\n"
        },
        {
          "title": "IconPositions",
          "code": "import React from 'react';\nimport { CollapsiblePanel } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<CollapsiblePanel iconPosition=\"end\" title=\"Icon End (default)\">...</CollapsiblePanel>\n<CollapsiblePanel iconPosition=\"start\" title=\"Icon Start\">...</CollapsiblePanel>`;\n\nconst IconPositions: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Icon Positions\" centered={false}>\n            <div className=\"space-y-3 w-full\">\n                <CollapsiblePanel iconPosition=\"end\" title=\"Icon at End\" subtitle=\"Default position — chevron on the right\" defaultOpen>\n                    <p className=\"text-sm leading-relaxed\">\n                        The toggle indicator sits at the trailing edge of the header. This is the default behavior.\n                    </p>\n                </CollapsiblePanel>\n                <CollapsiblePanel iconPosition=\"start\" title=\"Icon at Start\" subtitle=\"Chevron on the left, before the title\">\n                    <p className=\"text-sm leading-relaxed\">\n                        Placing the indicator at the start gives a tree-view or sidebar-style appearance.\n                    </p>\n                </CollapsiblePanel>\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} />\n        </div>\n    </>\n);\n\nexport default IconPositions;\n"
        },
        {
          "title": "MultiOpenGroup",
          "code": "import React from 'react';\nimport { CollapsiblePanel, CollapsiblePanelGroup } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<CollapsiblePanelGroup variant=\"separated\" defaultOpenKeys={['m-1', 'm-2']}>\n  <CollapsiblePanel id=\"m-1\" title=\"Panel A\">...</CollapsiblePanel>\n  <CollapsiblePanel id=\"m-2\" title=\"Panel B\">...</CollapsiblePanel>\n  <CollapsiblePanel id=\"m-3\" title=\"Panel C\">...</CollapsiblePanel>\n</CollapsiblePanelGroup>`;\n\nconst MultiOpenGroup: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Multi-Open Group\" centered={false}>\n            <div className=\"w-full\">\n                <CollapsiblePanelGroup variant=\"separated\" defaultOpenKeys={['mo-a', 'mo-b']}>\n                    <CollapsiblePanel id=\"mo-a\" title=\"Database Configuration\" subtitle=\"Connection strings, pooling, and timeouts\">\n                        <p className=\"text-sm leading-relaxed\">\n                            Configure your primary and replica database connections. Connection pool size defaults to 10\n                            with a 30-second idle timeout.\n                        </p>\n                    </CollapsiblePanel>\n                    <CollapsiblePanel id=\"mo-b\" title=\"Cache Layer\" subtitle=\"Redis and in-memory cache settings\">\n                        <p className=\"text-sm leading-relaxed\">\n                            Redis cluster mode is enabled by default. In-memory cache uses LRU eviction with a 256 MB cap.\n                        </p>\n                    </CollapsiblePanel>\n                    <CollapsiblePanel id=\"mo-c\" title=\"Message Queue\" subtitle=\"Kafka topics and consumer groups\">\n                        <p className=\"text-sm leading-relaxed\">\n                            Topics auto-create is disabled in production. Consumer group rebalance strategy is cooperative-sticky.\n                        </p>\n                    </CollapsiblePanel>\n                </CollapsiblePanelGroup>\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} />\n        </div>\n    </>\n);\n\nexport default MultiOpenGroup;\n"
        },
        {
          "title": "Sizes",
          "code": "import React from 'react';\nimport { CollapsiblePanel, CollapsiblePanelSize } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<CollapsiblePanel size=\"sm\" title=\"Small Panel\">...</CollapsiblePanel>\n<CollapsiblePanel size=\"md\" title=\"Medium Panel\">...</CollapsiblePanel>\n<CollapsiblePanel size=\"lg\" title=\"Large Panel\">...</CollapsiblePanel>`;\n\nconst sizes: { size: CollapsiblePanelSize; label: string }[] = [\n    { size: 'sm', label: 'Small' },\n    { size: 'md', label: 'Medium (default)' },\n    { size: 'lg', label: 'Large' },\n];\n\nconst Sizes: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Sizes\" centered={false}>\n            <div className=\"space-y-3 w-full\">\n                {sizes.map((s) => (\n                    <CollapsiblePanel\n                        key={s.size}\n                        size={s.size}\n                        title={`${s.label} Panel`}\n                        subtitle={`size=\"${s.size}\"`}\n                        defaultOpen\n                    >\n                        <p className=\"text-sm leading-relaxed\">\n                            Content rendered at the <strong>{s.size}</strong> size. Header padding,\n                            font size, and indicator icon all scale proportionally.\n                        </p>\n                    </CollapsiblePanel>\n                ))}\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} />\n        </div>\n    </>\n);\n\nexport default Sizes;\n"
        },
        {
          "title": "Variants",
          "code": "import React from 'react';\nimport { CollapsiblePanel, CollapsiblePanelVariant } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<CollapsiblePanel variant=\"default\" title=\"Default\" defaultOpen>...</CollapsiblePanel>\n<CollapsiblePanel variant=\"bordered\" title=\"Bordered\">...</CollapsiblePanel>\n<CollapsiblePanel variant=\"elevated\" title=\"Elevated\">...</CollapsiblePanel>\n<CollapsiblePanel variant=\"ghost\" title=\"Ghost\">...</CollapsiblePanel>\n<CollapsiblePanel variant=\"separated\" title=\"Separated\">...</CollapsiblePanel>`;\n\nconst variants: { name: CollapsiblePanelVariant; description: string }[] = [\n    { name: 'default', description: 'Subtle border with clean background. Best for general use.' },\n    { name: 'bordered', description: 'Prominent border that highlights on open with the primary accent color.' },\n    { name: 'elevated', description: 'Shadow-based depth. Gains more elevation when expanded.' },\n    { name: 'ghost', description: 'No background or border. Blends into surrounding content seamlessly.' },\n    { name: 'separated', description: 'Distinct header background with a divider line when open.' },\n];\n\nconst Variants: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Variants\" centered={false}>\n            <div className=\"space-y-3 w-full\">\n                {variants.map((v, i) => (\n                    <CollapsiblePanel\n                        key={v.name}\n                        variant={v.name}\n                        title={`${v.name.charAt(0).toUpperCase()}${v.name.slice(1)} Variant`}\n                        subtitle={v.description}\n                        defaultOpen={i === 0}\n                    >\n                        <p className=\"text-sm leading-relaxed\">\n                            This is the <strong>{v.name}</strong> variant. {v.description}\n                        </p>\n                    </CollapsiblePanel>\n                ))}\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} />\n        </div>\n    </>\n);\n\nexport default Variants;\n"
        },
        {
          "title": "WithIcons",
          "code": "import React from 'react';\nimport { CollapsiblePanel } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<CollapsiblePanel\n  title=\"Settings\"\n  icon={<GearIcon />}\n>\n  ...\n</CollapsiblePanel>`;\n\nconst settingsIcon = (\n    <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 20 20\" fill=\"currentColor\" style={{ width: 18, height: 18 }}>\n        <path fillRule=\"evenodd\" d=\"M7.84 1.804A1 1 0 0 1 8.82 1h2.36a1 1 0 0 1 .98.804l.331 1.652a6.993 6.993 0 0 1 1.929 1.115l1.598-.54a1 1 0 0 1 1.186.447l1.18 2.044a1 1 0 0 1-.205 1.251l-1.267 1.113a7.047 7.047 0 0 1 0 2.228l1.267 1.113a1 1 0 0 1 .206 1.25l-1.18 2.045a1 1 0 0 1-1.187.447l-1.598-.54a6.993 6.993 0 0 1-1.929 1.115l-.33 1.652a1 1 0 0 1-.98.804H8.82a1 1 0 0 1-.98-.804l-.331-1.652a6.993 6.993 0 0 1-1.929-1.115l-1.598.54a1 1 0 0 1-1.186-.447l-1.18-2.044a1 1 0 0 1 .205-1.251l1.267-1.114a7.05 7.05 0 0 1 0-2.227L1.821 7.773a1 1 0 0 1-.206-1.25l1.18-2.045a1 1 0 0 1 1.187-.447l1.598.54A6.992 6.992 0 0 1 7.51 3.456l.33-1.652ZM10 13a3 3 0 1 0 0-6 3 3 0 0 0 0 6Z\" clipRule=\"evenodd\" />\n    </svg>\n);\n\nconst lockIcon = (\n    <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 20 20\" fill=\"currentColor\" style={{ width: 18, height: 18 }}>\n        <path fillRule=\"evenodd\" d=\"M10 1a4.5 4.5 0 0 0-4.5 4.5V9H5a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-6a2 2 0 0 0-2-2h-.5V5.5A4.5 4.5 0 0 0 10 1Zm3 8V5.5a3 3 0 1 0-6 0V9h6Z\" clipRule=\"evenodd\" />\n    </svg>\n);\n\nconst bellIcon = (\n    <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 20 20\" fill=\"currentColor\" style={{ width: 18, height: 18 }}>\n        <path fillRule=\"evenodd\" d=\"M10 2a6 6 0 0 0-6 6c0 1.887-.454 3.665-1.257 5.234a.75.75 0 0 0 .515 1.076 32.91 32.91 0 0 0 3.256.508 3.5 3.5 0 0 0 6.972 0 32.903 32.903 0 0 0 3.256-.508.75.75 0 0 0 .515-1.076A11.448 11.448 0 0 1 16 8a6 6 0 0 0-6-6ZM8.05 14.943a33.54 33.54 0 0 0 3.9 0 2 2 0 0 1-3.9 0Z\" clipRule=\"evenodd\" />\n    </svg>\n);\n\nconst WithIcons: React.FC = () => (\n    <>\n        <ComponentDemo title=\"With Icons\" centered={false}>\n            <div className=\"space-y-3 w-full\">\n                <CollapsiblePanel title=\"General Settings\" icon={settingsIcon} defaultOpen>\n                    <p className=\"text-sm leading-relaxed\">\n                        Configure application-level settings like language, timezone, and display preferences.\n                    </p>\n                </CollapsiblePanel>\n                <CollapsiblePanel title=\"Security\" icon={lockIcon} subtitle=\"Manage authentication and permissions\">\n                    <p className=\"text-sm leading-relaxed\">\n                        Two-factor authentication, API keys, session management, and access control rules.\n                    </p>\n                </CollapsiblePanel>\n                <CollapsiblePanel title=\"Notifications\" icon={bellIcon}>\n                    <p className=\"text-sm leading-relaxed\">\n                        Email alerts, push notifications, and in-app notification preferences.\n                    </p>\n                </CollapsiblePanel>\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} />\n        </div>\n    </>\n);\n\nexport default WithIcons;\n"
        }
      ],
      "props": {
        "panelProps": {
          "title": {
            "type": "React.ReactNode",
            "required": true,
            "description": "Header text or element displayed in the panel header."
          },
          "children": {
            "type": "React.ReactNode",
            "required": true,
            "description": "Content rendered inside the collapsible body."
          },
          "subtitle": {
            "type": "React.ReactNode",
            "description": "Secondary text rendered below the title in the header."
          },
          "icon": {
            "type": "React.ReactNode",
            "description": "Icon element rendered before the title in the header."
          },
          "variant": {
            "type": "'default' | 'bordered' | 'elevated' | 'ghost' | 'separated'",
            "default": "'default'",
            "description": "Visual style of the panel. Group-level variant is used as fallback."
          },
          "size": {
            "type": "'sm' | 'md' | 'lg'",
            "default": "'md'",
            "description": "Controls header padding, font size, and indicator icon size."
          },
          "iconPosition": {
            "type": "'start' | 'end'",
            "default": "'end'",
            "description": "Position of the toggle chevron — before or after the title."
          },
          "expandIcon": {
            "type": "React.ReactNode",
            "description": "Custom icon shown when the panel is collapsed."
          },
          "collapseIcon": {
            "type": "React.ReactNode",
            "description": "Custom icon shown when the panel is expanded. Falls back to expandIcon."
          },
          "defaultOpen": {
            "type": "boolean",
            "default": "false",
            "description": "Whether the panel starts open (uncontrolled mode)."
          },
          "open": {
            "type": "boolean",
            "description": "Controlled open state. When set, the component is fully controlled."
          },
          "onToggle": {
            "type": "(open: boolean) => void",
            "description": "Called when the user toggles the panel. Receives the new open state."
          },
          "disabled": {
            "type": "boolean",
            "default": "false",
            "description": "Prevents toggling. Header shows not-allowed cursor and hover is suppressed."
          },
          "headerActions": {
            "type": "React.ReactNode",
            "description": "Interactive elements placed at the end of the header. Click events do not propagate."
          },
          "headerTemplate": {
            "type": "(props: { isOpen, toggle }) => ReactNode",
            "description": "Fully custom header renderer. When set, title/subtitle/icon/indicator are ignored."
          },
          "lazy": {
            "type": "boolean",
            "default": "false",
            "description": "Defers rendering content until the panel is first opened."
          },
          "destroyOnCollapse": {
            "type": "boolean",
            "default": "false",
            "description": "Unmounts content from the DOM when the panel is collapsed."
          },
          "className": {
            "type": "string",
            "description": "Additional CSS classes for the root element."
          },
          "headerClassName": {
            "type": "string",
            "description": "Additional CSS classes for the header element."
          },
          "contentClassName": {
            "type": "string",
            "description": "Additional CSS classes for the content wrapper."
          },
          "style": {
            "type": "React.CSSProperties",
            "description": "Inline styles for the root element."
          },
          "id": {
            "type": "string",
            "description": "Element ID. Also used as the group key in CollapsiblePanelGroup."
          },
          "headingLevel": {
            "type": "1 | 2 | 3 | 4 | 5 | 6",
            "default": "3",
            "description": "Heading level used for the panel title (h1-h6) so the page heading outline reflects the panel."
          }
        },
        "groupProps": {
          "children": {
            "type": "React.ReactNode",
            "required": true,
            "description": "CollapsiblePanel children to manage."
          },
          "accordion": {
            "type": "boolean",
            "default": "false",
            "description": "When true, only one panel can be open at a time."
          },
          "defaultOpenKeys": {
            "type": "string[]",
            "default": "[]",
            "description": "Array of panel IDs that start open."
          },
          "variant": {
            "type": "'default' | 'bordered' | 'elevated' | 'ghost' | 'separated'",
            "default": "'default'",
            "description": "Default variant for all child panels."
          },
          "size": {
            "type": "'sm' | 'md' | 'lg'",
            "default": "'md'",
            "description": "Default size for all child panels."
          },
          "iconPosition": {
            "type": "'start' | 'end'",
            "default": "'end'",
            "description": "Default icon position for all child panels."
          },
          "gap": {
            "type": "number",
            "description": "Gap in pixels between panels."
          },
          "onChange": {
            "type": "(openKeys: string[]) => void",
            "description": "Called when the set of open panels changes."
          },
          "className": {
            "type": "string",
            "description": "Additional CSS classes for the group container."
          },
          "style": {
            "type": "React.CSSProperties",
            "description": "Inline styles for the group container."
          },
          "headingLevel": {
            "type": "1 | 2 | 3 | 4 | 5 | 6",
            "description": "Default heading level for child panels. Defaults to 3 if neither group nor panel specifies one."
          }
        },
        "tabsProps": {
          "tabs": {
            "type": "CollapsibleTabItem[]",
            "required": true,
            "description": "Array of tab objects with id, label, isOpen, and render function."
          },
          "height": {
            "type": "number | string",
            "description": "Minimum height of the tabs container."
          },
          "minOpenTabs": {
            "type": "number",
            "default": "1",
            "description": "Minimum number of tabs that must stay open at any time."
          },
          "variant": {
            "type": "'default' | 'bordered' | 'elevated'",
            "default": "'default'",
            "description": "Visual style variant for the tabs layout."
          },
          "onTabToggle": {
            "type": "(tabId: string, isOpen: boolean) => void",
            "description": "Called when a tab is toggled."
          },
          "className": {
            "type": "string",
            "description": "Additional CSS classes for the container."
          },
          "style": {
            "type": "React.CSSProperties",
            "description": "Inline styles for the container."
          }
        }
      },
      "storyDir": "collapsible-panel"
    },
    "ColorPicker": {
      "name": "ColorPicker",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React, { useState } from 'react';\nimport { ColorPicker } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { ColorPicker } from 'fluxo-ui';\n\nconst [color, setColor] = useState('#3b82f6');\n\n<ColorPicker value={color} onChange={setColor} />\n\n<ColorPicker defaultValue=\"#22c55e\" />\n\n<ColorPicker defaultValue=\"#f43f5e\" showAlpha={false} />`;\n\nconst BasicUsage: React.FC = () => {\n    const [color, setColor] = useState('#3b82f6');\n\n    return (\n        <>\n            <ComponentDemo title=\"Default Color Picker\" description=\"Click the trigger to open the picker. Supports hex, RGB, and alpha editing.\">\n                <div className=\"space-y-6\">\n                    <div>\n                        <div className=\"text-sm mb-2 opacity-70\">Controlled ({color})</div>\n                        <ColorPicker value={color} onChange={(c) => setColor(c)} />\n                    </div>\n                    <div>\n                        <div className=\"text-sm mb-2 opacity-70\">Uncontrolled</div>\n                        <ColorPicker defaultValue=\"#22c55e\" />\n                    </div>\n                    <div>\n                        <div className=\"text-sm mb-2 opacity-70\">No alpha channel</div>\n                        <ColorPicker defaultValue=\"#f43f5e\" showAlpha={false} />\n                    </div>\n                    <div>\n                        <div className=\"text-sm mb-2 opacity-70\">Editable (type a hex code)</div>\n                        <ColorPicker variant=\"input\" editable defaultValue=\"#8b5cf6\" />\n                    </div>\n                    <div>\n                        <div className=\"text-sm mb-2 opacity-70\">Disabled</div>\n                        <ColorPicker defaultValue=\"#6366f1\" disabled />\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "CustomSwatches",
          "code": "import React from 'react';\nimport { ColorPicker } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst brandPalette = ['#0f172a', '#1e293b', '#334155', '#3b82f6', '#60a5fa', '#93c5fd', '#dbeafe', '#f97316', '#fb923c', '#fde68a'];\n\nconst code = `<ColorPicker\n  defaultValue=\"#3b82f6\"\n  swatches={['#0f172a', '#1e293b', '#3b82f6', '#60a5fa', '#fb923c']}\n/>\n\n<ColorPicker defaultValue=\"#3b82f6\" showSwatches={false} />\n\n<ColorPicker defaultValue=\"#3b82f6\" showInputs={false} showSwatches={false} />`;\n\nconst CustomSwatches: React.FC = () => (\n    <>\n        <ComponentDemo\n            title=\"Custom Swatches & Panel Toggles\"\n            description=\"Pass your own palette via the swatches prop, or hide input fields and swatches for a minimal picker.\"\n        >\n            <div className=\"space-y-6\">\n                <div>\n                    <div className=\"text-sm mb-2 opacity-70\">Brand palette</div>\n                    <ColorPicker defaultValue=\"#3b82f6\" swatches={brandPalette} />\n                </div>\n                <div>\n                    <div className=\"text-sm mb-2 opacity-70\">No swatches</div>\n                    <ColorPicker defaultValue=\"#22c55e\" showSwatches={false} />\n                </div>\n                <div>\n                    <div className=\"text-sm mb-2 opacity-70\">Minimal (canvas only)</div>\n                    <ColorPicker defaultValue=\"#f43f5e\" showInputs={false} showSwatches={false} showAlpha={false} />\n                </div>\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default CustomSwatches;\n"
        },
        {
          "title": "Formats",
          "code": "import React, { useState } from 'react';\nimport { ColorPicker } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<ColorPicker defaultValue=\"#3b82f6\" format=\"hex\" />\n<ColorPicker defaultValue=\"#22c55e\" format=\"rgb\" />\n<ColorPicker defaultValue=\"#f59e0b\" format=\"rgba\" />`;\n\nconst Formats: React.FC = () => {\n    const [hex, setHex] = useState('#3b82f6');\n    const [alpha, setAlpha] = useState(0.75);\n\n    return (\n        <>\n            <ComponentDemo title=\"Output Formats\" description=\"Display the current value in hex, rgb, or rgba format.\">\n                <div className=\"space-y-6\">\n                    <div>\n                        <div className=\"text-sm mb-2 opacity-70\">hex</div>\n                        <ColorPicker defaultValue=\"#3b82f6\" format=\"hex\" />\n                    </div>\n                    <div>\n                        <div className=\"text-sm mb-2 opacity-70\">rgb</div>\n                        <ColorPicker defaultValue=\"#22c55e\" format=\"rgb\" />\n                    </div>\n                    <div>\n                        <div className=\"text-sm mb-2 opacity-70\">rgba (controlled: {hex} @ {alpha.toFixed(2)})</div>\n                        <ColorPicker\n                            value={hex}\n                            alpha={alpha}\n                            format=\"rgba\"\n                            onChange={(c, a) => {\n                                setHex(c);\n                                setAlpha(a);\n                            }}\n                        />\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default Formats;\n"
        },
        {
          "title": "Sizes",
          "code": "import React from 'react';\nimport { ColorPicker } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<ColorPicker size=\"sm\" defaultValue=\"#3b82f6\" />\n<ColorPicker size=\"md\" defaultValue=\"#3b82f6\" />\n<ColorPicker size=\"lg\" defaultValue=\"#3b82f6\" />`;\n\nconst Sizes: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Sizes\" description=\"Three trigger sizes.\">\n            <div className=\"space-y-4\">\n                <div className=\"flex items-center gap-4\">\n                    <span className=\"text-xs opacity-60 w-8\">sm</span>\n                    <ColorPicker size=\"sm\" defaultValue=\"#3b82f6\" />\n                    <ColorPicker size=\"sm\" variant=\"swatch\" defaultValue=\"#22c55e\" />\n                </div>\n                <div className=\"flex items-center gap-4\">\n                    <span className=\"text-xs opacity-60 w-8\">md</span>\n                    <ColorPicker size=\"md\" defaultValue=\"#3b82f6\" />\n                    <ColorPicker size=\"md\" variant=\"swatch\" defaultValue=\"#22c55e\" />\n                </div>\n                <div className=\"flex items-center gap-4\">\n                    <span className=\"text-xs opacity-60 w-8\">lg</span>\n                    <ColorPicker size=\"lg\" defaultValue=\"#3b82f6\" />\n                    <ColorPicker size=\"lg\" variant=\"swatch\" defaultValue=\"#22c55e\" />\n                </div>\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default Sizes;\n"
        },
        {
          "title": "Variants",
          "code": "import React from 'react';\nimport { ColorPicker } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<ColorPicker variant=\"button\" defaultValue=\"#3b82f6\" />\n<ColorPicker variant=\"input\" defaultValue=\"#22c55e\" />\n<ColorPicker variant=\"swatch\" defaultValue=\"#f59e0b\" />`;\n\nconst Variants: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Trigger Variants\" description=\"Three trigger styles: button (icon + text), input (monospace code), and swatch (color-only).\">\n            <div className=\"space-y-6\">\n                <div>\n                    <div className=\"text-sm mb-2 opacity-70\">button (default)</div>\n                    <ColorPicker variant=\"button\" defaultValue=\"#3b82f6\" />\n                </div>\n                <div>\n                    <div className=\"text-sm mb-2 opacity-70\">input</div>\n                    <ColorPicker variant=\"input\" defaultValue=\"#22c55e\" />\n                </div>\n                <div>\n                    <div className=\"text-sm mb-2 opacity-70\">swatch</div>\n                    <div className=\"flex gap-2\">\n                        <ColorPicker variant=\"swatch\" defaultValue=\"#f59e0b\" />\n                        <ColorPicker variant=\"swatch\" defaultValue=\"#ef4444\" />\n                        <ColorPicker variant=\"swatch\" defaultValue=\"#8b5cf6\" />\n                        <ColorPicker variant=\"swatch\" defaultValue=\"#10b981\" />\n                    </div>\n                </div>\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default Variants;\n"
        }
      ],
      "props": {
        "colorPickerProps": {
          "value": {
            "type": "string",
            "description": "Controlled hex color value."
          },
          "defaultValue": {
            "type": "string",
            "default": "'#3b82f6'",
            "description": "Initial hex color for uncontrolled usage."
          },
          "alpha": {
            "type": "number",
            "description": "Controlled alpha value between 0 and 1."
          },
          "defaultAlpha": {
            "type": "number",
            "default": "1",
            "description": "Initial alpha value."
          },
          "format": {
            "type": "'hex' | 'rgb' | 'rgba'",
            "default": "'hex'",
            "description": "Format used for the displayed trigger text."
          },
          "size": {
            "type": "'sm' | 'md' | 'lg'",
            "default": "'md'",
            "description": "Trigger size."
          },
          "variant": {
            "type": "'button' | 'input' | 'swatch'",
            "default": "'button'",
            "description": "Trigger visual style."
          },
          "disabled": {
            "type": "boolean",
            "default": "false",
            "description": "Disable interaction."
          },
          "readOnly": {
            "type": "boolean",
            "default": "false",
            "description": "Display-only mode."
          },
          "editable": {
            "type": "boolean",
            "default": "false",
            "description": "When used with variant='input', renders a real text input so users can type a hex code manually. Valid hex updates the color live."
          },
          "showAlpha": {
            "type": "boolean",
            "default": "true",
            "description": "Show the alpha slider and input."
          },
          "showInputs": {
            "type": "boolean",
            "default": "true",
            "description": "Show hex/RGB/alpha input fields."
          },
          "showSwatches": {
            "type": "boolean",
            "default": "true",
            "description": "Show the preset swatches grid."
          },
          "swatches": {
            "type": "string[]",
            "description": "Custom palette of hex swatches."
          },
          "placeholder": {
            "type": "string",
            "default": "'Pick a color'",
            "description": "ARIA label when none is provided."
          },
          "onChange": {
            "type": "(value: string, alpha: number) => void",
            "description": "Called when the color or alpha changes."
          },
          "onOpenChange": {
            "type": "(open: boolean) => void",
            "description": "Called when the popover opens or closes."
          }
        }
      },
      "storyDir": "color-picker"
    },
    "CommandPalette": {
      "name": "CommandPalette",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React, { useState } from 'react';\nimport {\n    CopyIcon,\n    DashboardIcon,\n    EditIcon,\n    SearchIcon,\n    SettingsIcon,\n    ShareIcon,\n    TrashIcon,\n    UserIcon,\n} from '../../../assets/icons';\nimport { Button, CommandPalette, CommandPaletteCommand } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { CommandPalette } from 'fluxo-ui';\n\nconst [open, setOpen] = useState(false);\nconst [last, setLast] = useState('');\n\nconst commands = [\n  { id: 'new', title: 'New file', group: 'File', shortcut: '⌘N', icon: EditIcon, onSelect: () => setLast('new') },\n  { id: 'open', title: 'Open file', group: 'File', shortcut: '⌘O', icon: CopyIcon, onSelect: () => setLast('open') },\n  { id: 'settings', title: 'Open settings', group: 'App', shortcut: '⌘,', icon: SettingsIcon, onSelect: () => setLast('settings') },\n];\n\n<CommandPalette open={open} onOpenChange={setOpen} commands={commands} />`;\n\nconst BasicUsage: React.FC = () => {\n    const [open, setOpen] = useState(false);\n    const [last, setLast] = useState('');\n\n    const commands: CommandPaletteCommand[] = [\n        { id: 'dashboard', title: 'Open dashboard', subtitle: 'Go to the main dashboard', group: 'Navigation', icon: DashboardIcon, shortcut: '⌘D', onSelect: () => setLast('dashboard') },\n        { id: 'profile', title: 'View profile', group: 'Navigation', icon: UserIcon, onSelect: () => setLast('profile') },\n        { id: 'search', title: 'Search', group: 'Actions', icon: SearchIcon, shortcut: '⌘F', onSelect: () => setLast('search') },\n        { id: 'new', title: 'Create new file', subtitle: 'Start a blank document', group: 'Actions', icon: EditIcon, shortcut: '⌘N', onSelect: () => setLast('new') },\n        { id: 'duplicate', title: 'Duplicate', group: 'Actions', icon: CopyIcon, shortcut: '⌘D', onSelect: () => setLast('duplicate') },\n        { id: 'share', title: 'Share', group: 'Actions', icon: ShareIcon, onSelect: () => setLast('share') },\n        { id: 'settings', title: 'Open settings', group: 'App', icon: SettingsIcon, shortcut: '⌘,', onSelect: () => setLast('settings') },\n        { id: 'delete', title: 'Delete current item', subtitle: 'This cannot be undone', group: 'Actions', danger: true, icon: TrashIcon, onSelect: () => setLast('delete') },\n    ];\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Default Command Palette\"\n                description=\"Open with ⌘K (or Ctrl+K) or click the button. Type to filter, arrow keys to navigate, Enter to run, Esc to close.\"\n            >\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16, alignItems: 'center' }}>\n                    <Button onClick={() => setOpen(true)} variant=\"primary\">\n                        Open Command Palette (⌘K)\n                    </Button>\n                    <div\n                        style={{\n                            padding: '10px 14px',\n                            background: 'var(--eui-bg-subtle)',\n                            border: '1px solid var(--eui-border-subtle)',\n                            borderRadius: 6,\n                            fontSize: 13,\n                            minWidth: 240,\n                            textAlign: 'center',\n                        }}\n                    >\n                        Last command: <strong>{last || '—'}</strong>\n                    </div>\n                </div>\n            </ComponentDemo>\n            <CommandPalette\n                open={open}\n                onOpenChange={setOpen}\n                commands={commands}\n                hotkey=\"mod+k\"\n                recents={{ storageKey: 'fluxo-ui-cmdp-demo' }}\n            />\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "Customization",
          "code": "import React, { useState } from 'react';\nimport { Button, CommandPalette, CommandPaletteCommand } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<CommandPalette\n  open={open}\n  onOpenChange={setOpen}\n  commands={commands}\n  hotkey=\"mod+/\"\n  placeholder=\"Type to search...\"\n  emptyMessage={<span>Nothing matches \"{query}\"</span>}\n  groupOrder={['Navigation', 'Actions']}\n  maxResults={20}\n/>`;\n\nconst Customization: React.FC = () => {\n    const [open, setOpen] = useState(false);\n    const [last, setLast] = useState('');\n\n    const commands: CommandPaletteCommand[] = [\n        { id: 'home', title: 'Go to home', group: 'Navigation', keywords: ['dashboard', 'main'], onSelect: () => setLast('home') },\n        { id: 'docs', title: 'Open documentation', group: 'Navigation', onSelect: () => setLast('docs') },\n        { id: 'changelog', title: 'View changelog', group: 'Navigation', onSelect: () => setLast('changelog') },\n        { id: 'export', title: 'Export current view', group: 'Actions', onSelect: () => setLast('export') },\n        { id: 'import', title: 'Import data', group: 'Actions', onSelect: () => setLast('import') },\n        { id: 'reset', title: 'Reset workspace', group: 'Actions', danger: true, onSelect: () => setLast('reset') },\n        { id: 'preview', title: 'Preview only', group: 'Disabled', disabled: true, onSelect: () => setLast('preview') },\n    ];\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Custom hotkey, group order, placeholder, empty message\"\n                description=\"Open with mod+/. Hidden command items (disabled) are visually dimmed and not selectable.\"\n            >\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16, alignItems: 'center' }}>\n                    <Button onClick={() => setOpen(true)} variant=\"primary\">\n                        Open palette (mod+/)\n                    </Button>\n                    <div\n                        style={{\n                            padding: '10px 14px',\n                            background: 'var(--eui-bg-subtle)',\n                            border: '1px solid var(--eui-border-subtle)',\n                            borderRadius: 6,\n                            fontSize: 13,\n                            minWidth: 240,\n                            textAlign: 'center',\n                        }}\n                    >\n                        Last command: <strong>{last || '—'}</strong>\n                    </div>\n                </div>\n            </ComponentDemo>\n            <CommandPalette\n                open={open}\n                onOpenChange={setOpen}\n                hotkey=\"mod+/\"\n                placeholder=\"Type to filter — try 'export' or 'reset'…\"\n                emptyMessage=\"No matches yet.\"\n                groupOrder={['Navigation', 'Actions', 'Disabled']}\n                maxResults={20}\n                commands={commands}\n            />\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default Customization;\n"
        }
      ],
      "props": {
        "commandPaletteProps": {
          "commands": {
            "type": "Array<CommandPaletteCommand>",
            "required": true,
            "description": "Registered commands: { id, title, subtitle?, group?, keywords?, icon?, shortcut?, onSelect, disabled?, danger? }"
          },
          "open": {
            "type": "boolean",
            "description": "Controlled open state"
          },
          "onOpenChange": {
            "type": "(open: boolean) => void",
            "description": "Called when the palette opens or closes"
          },
          "hotkey": {
            "type": "string",
            "default": "'mod+k'",
            "description": "Global hotkey to toggle the palette ('mod' = Cmd on Mac, Ctrl elsewhere)"
          },
          "placeholder": {
            "type": "string",
            "default": "'Type a command or search...'",
            "description": "Search input placeholder"
          },
          "emptyMessage": {
            "type": "string | ReactNode",
            "default": "'No commands found'",
            "description": "Shown when no commands match the query"
          },
          "recents": {
            "type": "{ storageKey?: string; limit?: number }",
            "description": "When provided, persists recently selected ids to localStorage"
          },
          "groupOrder": {
            "type": "string[]",
            "description": "Explicit ordering of group headings"
          },
          "maxResults": {
            "type": "number",
            "default": "50",
            "description": "Maximum number of items to show"
          },
          "filterFn": {
            "type": "(command, query: string) => number",
            "description": "Custom scorer; return 0 to hide. Default: subsequence match on title/keywords/group"
          },
          "id": {
            "type": "string",
            "description": "HTML id attribute"
          },
          "className": {
            "type": "string",
            "description": "Additional CSS classes"
          },
          "ariaLabel": {
            "type": "string",
            "default": "'Command palette'",
            "description": "Accessible label for the dialog"
          }
        }
      },
      "storyDir": "command-palette"
    },
    "ConfirmPopover": {
      "name": "ConfirmPopover",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "ConfirmCustomDemo",
          "code": "import React from 'react';\nimport { Button, Confirm } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst placements = ['topLeft', 'top', 'topRight', 'left', 'right', 'bottomLeft', 'bottom', 'bottomRight'] as const;\n\nconst code = `Confirm.confirm(\n  e.currentTarget as HTMLElement,\n  'Submit the form? All data will be saved.',\n  () => handleSubmit(),\n  undefined,\n  { title: 'Submit Form', confirmText: 'Submit', cancelText: 'Not yet', placement: 'topLeft' }\n);`;\n\nconst ConfirmCustomDemo: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo title=\"Placement options\" description=\"Click each button to see the popover in that position.\">\n                <div className=\"flex gap-3 flex-wrap justify-center\">\n                    {placements.map((placement) => (\n                        <Button\n                            key={placement}\n                            variant=\"primary\"\n                            size=\"sm\"\n                            onClick={(e) => {\n                                Confirm.confirm(\n                                    e.currentTarget as HTMLElement,\n                                    'Submit the form? All data will be saved.',\n                                    () => console.log('Confirmed'),\n                                    undefined,\n                                    { title: 'Submit Form', confirmText: 'Submit', cancelText: 'Not yet', placement }\n                                );\n                            }}\n                        >\n                            {placement}\n                        </Button>\n                    ))}\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default ConfirmCustomDemo;\n"
        },
        {
          "title": "CustomActionsDemo",
          "code": "import React from 'react';\nimport { Button, Confirm } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `Confirm.show({\n  target: e.currentTarget as HTMLElement,\n  title: 'Choose action',\n  message: 'What would you like to do with this record?',\n  placement: 'auto',\n  actions: [\n    { label: 'Archive', variant: 'warning', layout: 'outlined', onClick: () => archive() },\n    { label: 'Delete', variant: 'danger', layout: 'default', onClick: () => remove() },\n  ],\n});`;\n\nconst CustomActionsDemo: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo title=\"Low-level API with custom action set\">\n                <Button\n                    variant=\"secondary\"\n                    onClick={(e) => {\n                        Confirm.show({\n                            target: e.currentTarget as HTMLElement,\n                            title: 'Choose action',\n                            message: 'What would you like to do with this record?',\n                            placement: 'auto',\n                            actions: [\n                                { label: 'Archive', variant: 'warning', layout: 'outlined', onClick: () => console.log('archived') },\n                                { label: 'Delete', variant: 'danger', layout: 'default', onClick: () => console.log('deleted') },\n                            ],\n                        });\n                    }}\n                >\n                    Custom Actions\n                </Button>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default CustomActionsDemo;\n"
        },
        {
          "title": "InfoOkDemo",
          "code": "import React from 'react';\nimport { Button, Confirm } from '../../../components';\nimport { InfoIcon, CheckCircleIcon } from '../../../assets/icons';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `Confirm.ok(\n  e.currentTarget as HTMLElement,\n  'Your changes have been saved automatically.',\n  undefined,\n  { title: 'Auto-saved', icon: CheckCircleIcon, okText: 'Got it' }\n);`;\n\nconst InfoOkDemo: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo title=\"Single-button informational popover\">\n                <Button\n                    variant=\"info\"\n                    layout=\"outlined\"\n                    leftIcon={<InfoIcon className=\"w-4 h-4\" />}\n                    onClick={(e) => {\n                        Confirm.ok(\n                            e.currentTarget as HTMLElement,\n                            'Your changes have been saved automatically.',\n                            undefined,\n                            { title: 'Auto-saved', icon: CheckCircleIcon, okText: 'Got it' }\n                        );\n                    }}\n                >\n                    Show Info\n                </Button>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default InfoOkDemo;\n"
        },
        {
          "title": "RichJsxDemo",
          "code": "import React from 'react';\nimport { Button, Confirm } from '../../../components';\nimport { WarningIcon } from '../../../assets/icons';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `Confirm.yesNo(\n  e.currentTarget as HTMLElement,\n  <div className=\"space-y-2\">\n    <p className=\"font-medium\">This will permanently remove:</p>\n    <ul className=\"list-disc list-inside text-xs\">\n      <li>All associated records</li>\n      <li>Media files and attachments</li>\n    </ul>\n  </div>,\n  () => handleDelete(),\n  undefined,\n  { title: 'Destructive Action', icon: WarningIcon }\n);`;\n\nconst RichJsxDemo: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo title=\"ReactNode as message\" description=\"The message prop accepts any React node for complex content.\">\n                <Button\n                    variant=\"warning\"\n                    leftIcon={<WarningIcon className=\"w-4 h-4\" />}\n                    onClick={(e) => {\n                        Confirm.yesNo(\n                            e.currentTarget as HTMLElement,\n                            <div className=\"space-y-2\">\n                                <p className=\"font-medium\">This will permanently remove:</p>\n                                <ul className=\"list-disc list-inside text-xs space-y-1 text-theme-muted\">\n                                    <li>All associated records</li>\n                                    <li>Media files and attachments</li>\n                                    <li>Audit history</li>\n                                </ul>\n                            </div>,\n                            () => console.log('Confirmed'),\n                            undefined,\n                            { title: 'Destructive Action', icon: WarningIcon }\n                        );\n                    }}\n                >\n                    Rich Message\n                </Button>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default RichJsxDemo;\n"
        },
        {
          "title": "SetupSection",
          "code": "import React from 'react';\nimport { CodeBlock } from '../../CodeBlock';\n\nconst code = `import { ConfirmPopoverManager } from 'fluxo-ui';\n\nfunction App() {\n  return (\n    <>\n      <ConfirmPopoverManager />\n      {/* rest of app */}\n    </>\n  );\n}`;\n\nconst SetupSection: React.FC = () => {\n    return <CodeBlock title=\"App root\" code={code} />;\n};\n\nexport default SetupSection;\n"
        },
        {
          "title": "YesNoDemo",
          "code": "import React from 'react';\nimport { Button, Confirm } from '../../../components';\nimport { TrashIcon } from '../../../assets/icons';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `Confirm.yesNo(\n  e.currentTarget as HTMLElement,\n  'Are you sure you want to delete this item?',\n  () => handleDelete(),\n  () => console.log('Cancelled'),\n  { title: 'Delete Item', icon: TrashIcon }\n);`;\n\nconst YesNoDemo: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo title=\"Delete confirmation\" description=\"Classic yes/no anchored to the clicked element.\">\n                <Button\n                    variant=\"danger\"\n                    layout=\"outlined\"\n                    leftIcon={<TrashIcon className=\"w-4 h-4\" />}\n                    onClick={(e) => {\n                        Confirm.yesNo(\n                            e.currentTarget as HTMLElement,\n                            'Are you sure you want to delete this item? This action cannot be undone.',\n                            () => console.log('Deleted!'),\n                            () => console.log('Cancelled'),\n                            { title: 'Delete Item', icon: TrashIcon }\n                        );\n                    }}\n                >\n                    Delete Item\n                </Button>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default YesNoDemo;\n"
        }
      ],
      "props": {
        "confirmPopoverProps": {
          "target": {
            "type": "HTMLElement",
            "required": true,
            "description": "The element the popover is anchored to (typically event.currentTarget)"
          },
          "message": {
            "type": "string | ReactNode",
            "required": true,
            "description": "The body message. Supports plain strings or JSX for rich content."
          },
          "title": {
            "type": "string",
            "description": "Optional heading displayed at the top of the popover."
          },
          "icon": {
            "type": "ComponentType | ReactElement",
            "description": "Optional icon shown next to the title."
          },
          "placement": {
            "type": "'top' | 'topLeft' | 'topRight' | 'bottom' | 'bottomLeft' | 'bottomRight' | 'left' | 'right' | 'auto'",
            "default": "auto",
            "description": "Where to place the popover relative to the target. 'auto' picks the best position based on available space."
          },
          "actions": {
            "type": "ConfirmPopoverAction[]",
            "required": true,
            "description": "Buttons rendered in the footer. Each action has label, onClick, variant, and layout."
          },
          "onClose": {
            "type": "() => void",
            "description": "Called when the popover is dismissed via Escape key or an outside click."
          },
          "headingLevel": {
            "type": "1 | 2 | 3 | 4 | 5 | 6",
            "default": "3",
            "description": "Heading element level used for the title (h1-h6) so it integrates with the page heading outline."
          },
          "defaultActionIndex": {
            "type": "number",
            "description": "Index of the action to auto-focus when the popover opens. Defaults to the first non-danger action when destructive variants exist, otherwise the last action."
          }
        },
        "staticMethodProps": {
          "Confirm.yesNo(target, message, onConfirm, onCancel?, options?)": {
            "type": "method",
            "description": "Shows a popover with Yes / No buttons. Fires onConfirm on Yes, onCancel on No."
          },
          "Confirm.confirm(target, message, onConfirm, onCancel?, options?)": {
            "type": "method",
            "description": "Shows a popover with customisable Confirm / Cancel buttons. options accepts confirmText and cancelText."
          },
          "Confirm.ok(target, message, onOk?, options?)": {
            "type": "method",
            "description": "Shows an informational popover with a single OK button. options accepts okText."
          },
          "Confirm.show(options)": {
            "type": "method",
            "description": "Low-level method accepting a full ConfirmPopoverOptions object for maximum flexibility."
          },
          "Confirm.close(id?)": {
            "type": "method",
            "description": "Programmatically close a specific popover by id, or all popovers when called without arguments."
          }
        }
      },
      "storyDir": "confirm-popover"
    },
    "ContextMenu": {
      "name": "ContextMenu",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "ButtonTriggered",
          "code": "import React from 'react';\nimport { Button, showContextMenu } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { basicMenuItems } from './context-menu-story-data';\n\nconst ButtonTriggered: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo title=\"Click button to open menu\" description=\"Use onClick instead of onContextMenu for button-triggered menus.\">\n                <Button\n                    variant=\"secondary\"\n                    layout=\"outlined\"\n                    onClick={(e) => {\n                        const syntheticEvent = {\n                            ...e,\n                            preventDefault: () => {},\n                        } as React.MouseEvent;\n                        showContextMenu(syntheticEvent, basicMenuItems);\n                    }}\n                >\n                    Open Menu\n                </Button>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock\n                    code={`<Button onClick={(e) => showContextMenu(e as React.MouseEvent, menuItems)}>\n  Open Menu\n</Button>`}\n                />\n            </div>\n        </>\n    );\n};\n\nexport default ButtonTriggered;\n"
        },
        {
          "title": "NestedSubmenus",
          "code": "import React from 'react';\nimport { showContextMenu } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { nestedMenuItems } from './context-menu-story-data';\n\nconst NestedSubmenus: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo\n                title=\"Sub-menu items\"\n                description=\"Right-click to see nested menu items. Hover over 'Export' to reveal sub-options.\"\n            >\n                <div\n                    onContextMenu={(e) => showContextMenu(e, nestedMenuItems)}\n                    className=\"w-full h-40 rounded-lg border-2 border-dashed border-blue-500 dark:border-blue-700 flex items-center justify-center text-gray-500 dark:text-gray-400 select-none cursor-context-menu hover:border-blue-400 dark:hover:border-blue-500 transition-colors\"\n                >\n                    Right-click for nested menu\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock\n                    code={`const menuItems = [\n  { label: 'View Details', icon: <InfoIcon /> },\n  {\n    label: 'Export',\n    icon: <DownloadIcon />,\n    items: [\n      { label: 'Export as CSV', command: () => exportCsv() },\n      { label: 'Export as PDF', command: () => exportPdf() },\n      { label: 'Export as JSON', command: () => exportJson() },\n    ],\n  },\n  { seperator: true },\n  { label: 'Delete', icon: <TrashIcon />, command: () => handleDelete() },\n];`}\n                />\n            </div>\n        </>\n    );\n};\n\nexport default NestedSubmenus;\n"
        },
        {
          "title": "RightClickMenu",
          "code": "import React, { useRef } from 'react';\nimport { showContextMenu } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { basicMenuItems } from './context-menu-story-data';\n\nconst RightClickMenu: React.FC = () => {\n    const contextAreaRef = useRef<HTMLDivElement>(null);\n\n    return (\n        <>\n            <ComponentDemo title=\"Right-click area\" description=\"Right-click anywhere in the shaded area to open the context menu.\">\n                <div\n                    ref={contextAreaRef}\n                    onContextMenu={(e) => showContextMenu(e, basicMenuItems)}\n                    className=\"w-full h-40 rounded-lg border-2 border-dashed border-gray-400 dark:border-gray-600 flex items-center justify-center text-gray-500 dark:text-gray-400 select-none cursor-context-menu hover:border-gray-500 dark:hover:border-gray-500 transition-colors\"\n                >\n                    Right-click here\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock\n                    code={`import { showContextMenu } from 'fluxo-ui';\n\nconst menuItems = [\n  { label: 'Edit', icon: <EditIcon />, command: () => handleEdit() },\n  { label: 'Duplicate', icon: <CopyIcon />, command: () => handleDuplicate() },\n  { seperator: true },\n  { label: 'Delete', icon: <TrashIcon />, command: () => handleDelete() },\n];\n\n<div onContextMenu={(e) => showContextMenu(e, menuItems)}>\n  Right-click here\n</div>`}\n                />\n            </div>\n        </>\n    );\n};\n\nexport default RightClickMenu;\n"
        },
        {
          "title": "ScrollableMenu",
          "code": "import React from 'react';\nimport { showContextMenu } from '../../../components';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { longMenuItems } from './context-menu-story-data';\n\nconst ScrollableMenu: React.FC = () => {\n    return (\n        <ComponentDemo\n            title=\"Scrollable menu\"\n            description=\"Right-click to open a long menu. Hover near the top or bottom arrow to scroll without a scrollbar.\"\n        >\n            <div\n                onContextMenu={(e) => showContextMenu(e, longMenuItems)}\n                className=\"w-full h-40 rounded-lg border-2 border-dashed border-purple-500 dark:border-purple-700 flex items-center justify-center text-gray-500 dark:text-gray-400 select-none cursor-context-menu hover:border-purple-400 dark:hover:border-purple-500 transition-colors\"\n            >\n                Right-click for long scrollable menu\n            </div>\n        </ComponentDemo>\n    );\n};\n\nexport default ScrollableMenu;\n"
        },
        {
          "title": "SetupSection",
          "code": "import React from 'react';\nimport { CodeBlock } from '../../CodeBlock';\n\nconst SetupSection: React.FC = () => {\n    return (\n        <CodeBlock\n            title=\"App root\"\n            code={`import { ContextMenuManager } from 'fluxo-ui';\n\nfunction App() {\n  return (\n    <>\n      <ContextMenuManager />\n      {/* rest of app */}\n    </>\n  );\n}`}\n        />\n    );\n};\n\nexport default SetupSection;\n"
        },
        {
          "title": "TableRowMenu",
          "code": "import React from 'react';\nimport { showContextMenu, Table } from '../../../components';\nimport { EditIcon, TrashIcon, CopyIcon } from '../../../assets/icons';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { tableRows, tableColumns } from './context-menu-story-data';\n\nconst TableRowMenu: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo title=\"Per-row actions\" description=\"Right-click on any row to see row-specific actions.\" centered={false}>\n                <div\n                    className=\"w-full cursor-context-menu\"\n                    onContextMenu={(e) => {\n                        const tr = (e.target as HTMLElement).closest('tbody tr');\n                        if (!tr || !tr.parentElement) return;\n                        const rowIndex = Array.from(tr.parentElement.children).indexOf(tr);\n                        const row = tableRows[rowIndex];\n                        if (!row) return;\n                        showContextMenu(e, [\n                            { label: `Edit ${row.name}`, icon: <EditIcon className=\"w-4 h-4\" />, command: () => console.log('Edit', row.id) },\n                            { label: 'Duplicate', icon: <CopyIcon className=\"w-4 h-4\" />, command: () => console.log('Dup', row.id) },\n                            { seperator: true },\n                            { label: 'Delete', icon: <TrashIcon className=\"w-4 h-4\" />, command: () => console.log('Del', row.id) },\n                        ]);\n                    }}\n                >\n                    <Table\n                        columns={tableColumns}\n                        rows={tableRows}\n                        totalRows={tableRows.length}\n                        pagination={false}\n                    />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock\n                    code={`rows.map((row) => (\n  <tr\n    key={row.id}\n    onContextMenu={(e) =>\n      showContextMenu(e, [\n        { label: \\`Edit \\${row.name}\\`, icon: <EditIcon />, command: () => handleEdit(row.id) },\n        { seperator: true },\n        { label: 'Delete', icon: <TrashIcon />, command: () => handleDelete(row.id) },\n      ])\n    }\n  >\n    ...\n  </tr>\n))`}\n                />\n            </div>\n        </>\n    );\n};\n\nexport default TableRowMenu;\n"
        },
        {
          "title": "context-menu-story-data",
          "code": "import { EditIcon, TrashIcon, CopyIcon, InfoIcon, DownloadIcon, CheckCircleIcon } from '../../../assets/icons';\nimport type { Column } from '../../../components/table/table-types';\n\nexport const basicMenuItems = [\n    { label: 'Edit', icon: <EditIcon className=\"w-4 h-4\" />, command: () => console.log('Edit') },\n    { label: 'Duplicate', icon: <CopyIcon className=\"w-4 h-4\" />, command: () => console.log('Duplicate') },\n    { seperator: true },\n    { label: 'Download', icon: <DownloadIcon className=\"w-4 h-4\" />, command: () => console.log('Download') },\n    { seperator: true },\n    { label: 'Delete', icon: <TrashIcon className=\"w-4 h-4\" />, command: () => console.log('Delete') },\n];\n\nexport const longMenuItems = [\n    { label: 'Dashboard Overview', icon: <InfoIcon className=\"w-4 h-4\" />, command: () => console.log('Dashboard') },\n    { label: 'Analytics & Reports', icon: <InfoIcon className=\"w-4 h-4\" />, command: () => console.log('Analytics') },\n    { label: 'User Management', icon: <EditIcon className=\"w-4 h-4\" />, command: () => console.log('Users') },\n    { label: 'Role & Permission Settings', icon: <EditIcon className=\"w-4 h-4\" />, command: () => console.log('Roles') },\n    { seperator: true },\n    { label: 'Import Data', icon: <DownloadIcon className=\"w-4 h-4\" />, command: () => console.log('Import') },\n    { label: 'Export All Records as CSV', icon: <DownloadIcon className=\"w-4 h-4\" />, command: () => console.log('Export CSV') },\n    { label: 'Export All Records as PDF', icon: <DownloadIcon className=\"w-4 h-4\" />, command: () => console.log('Export PDF') },\n    { seperator: true },\n    { label: 'Archive Selected Items', icon: <CopyIcon className=\"w-4 h-4\" />, command: () => console.log('Archive') },\n    { label: 'Duplicate & Create Copy', icon: <CopyIcon className=\"w-4 h-4\" />, command: () => console.log('Duplicate') },\n    { label: 'Move to Another Folder or Workspace', icon: <EditIcon className=\"w-4 h-4\" />, command: () => console.log('Move') },\n    { seperator: true },\n    { label: 'Share with Team Members', icon: <CheckCircleIcon className=\"w-4 h-4\" />, command: () => console.log('Share') },\n    { label: 'Publish to Public', icon: <CheckCircleIcon className=\"w-4 h-4\" />, command: () => console.log('Publish') },\n    { label: 'Schedule for Later', icon: <InfoIcon className=\"w-4 h-4\" />, command: () => console.log('Schedule') },\n    { seperator: true },\n    { label: 'View Audit Log', icon: <InfoIcon className=\"w-4 h-4\" />, command: () => console.log('Audit') },\n    { label: 'Delete Permanently', icon: <TrashIcon className=\"w-4 h-4\" />, command: () => console.log('Delete') },\n];\n\nexport const nestedMenuItems = [\n    { label: 'View Details', icon: <InfoIcon className=\"w-4 h-4\" />, command: () => console.log('View Details') },\n    {\n        label: 'Export',\n        icon: <DownloadIcon className=\"w-4 h-4\" />,\n        items: [\n            { label: 'Export as CSV', command: () => console.log('CSV') },\n            { label: 'Export as PDF', command: () => console.log('PDF') },\n            { label: 'Export as JSON', command: () => console.log('JSON') },\n        ],\n    },\n    { seperator: true },\n    { label: 'Mark as Done', icon: <CheckCircleIcon className=\"w-4 h-4\" />, command: () => console.log('Done') },\n    { seperator: true },\n    { label: 'Delete', icon: <TrashIcon className=\"w-4 h-4\" />, command: () => console.log('Delete') },\n];\n\nexport const tableRows = [\n    { id: 1, name: 'Alice Johnson', role: 'Admin', status: 'Active' },\n    { id: 2, name: 'Bob Smith', role: 'Editor', status: 'Active' },\n    { id: 3, name: 'Carol White', role: 'Viewer', status: 'Inactive' },\n];\n\nexport const tableColumns: Column[] = [\n    { title: 'Name', field: 'name' },\n    { title: 'Role', field: 'role' },\n    { title: 'Status', field: 'status' },\n];\n"
        }
      ],
      "props": {
        "contextMenuManagerProps": {
          "No props required": {
            "type": "—",
            "description": "ContextMenuManager is a singleton. Mount it once at the app root; it manages all context menu state internally."
          }
        },
        "showContextMenuProps": {
          "event": {
            "type": "React.MouseEvent",
            "required": true,
            "description": "The mouse event from onContextMenu or onClick. Used to position the menu."
          },
          "menus": {
            "type": "MenuItem[]",
            "required": true,
            "description": "Array of menu items to display."
          },
          "options": {
            "type": "ContextMenuOptions",
            "description": "Optional configuration — currently supports placement (PlacementCorners)."
          }
        },
        "menuItemProps": {
          "label": {
            "type": "string",
            "description": "Text shown for the menu item."
          },
          "icon": {
            "type": "ReactNode",
            "description": "Optional icon placed before the label."
          },
          "command": {
            "type": "(id?: any) => void",
            "description": "Callback invoked when the item is clicked."
          },
          "separator": {
            "type": "boolean",
            "description": "When true, renders a visual divider instead of a clickable item."
          },
          "seperator": {
            "type": "boolean",
            "description": "Deprecated. Misspelled alias for `separator` kept for backwards compatibility — prefer `separator` in new code."
          },
          "items": {
            "type": "MenuItemBase[]",
            "description": "Nested sub-menu items (one level deep)."
          },
          "id": {
            "type": "any",
            "description": "Optional identifier passed to the command callback."
          }
        }
      },
      "storyDir": "context-menu"
    },
    "CountdownTimer": {
      "name": "CountdownTimer",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React, { useState } from 'react';\nimport { CountdownTimer } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { CountdownTimer } from 'fluxo-ui';\n\n<CountdownTimer\n  duration={30}\n  variant=\"circular\"\n  size=\"md\"\n  onComplete={() => console.log('Done!')}\n/>`;\n\nconst BasicUsage: React.FC = () => {\n    const [log, setLog] = useState('—');\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Basic Circular Timer\"\n                description=\"A 30-second circular countdown. Progress ring shrinks as time runs out. Pause and reset via the controls below.\"\n            >\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 16 }}>\n                    <CountdownTimer\n                        duration={30}\n                        variant=\"circular\"\n                        size=\"md\"\n                        onComplete={() => setLog('Timer completed!')}\n                        onTick={(rem: number) => setLog(`${rem}s remaining`)}\n                        onPause={(rem: number) => setLog(`Paused at ${rem}s`)}\n                        onReset={() => setLog('Reset')}\n                    />\n                    <div\n                        style={{\n                            padding: '10px 16px',\n                            background: 'var(--eui-bg-subtle)',\n                            border: '1px solid var(--eui-border-subtle)',\n                            borderRadius: 6,\n                            fontSize: 13,\n                            color: 'var(--eui-text-muted)',\n                        }}\n                    >\n                        Event: <strong style={{ color: 'var(--eui-text)' }}>{log}</strong>\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "ColorThresholds",
          "code": "import React from 'react';\nimport { CountdownTimer } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\n// Short duration so the thresholds are visibly crossed within seconds of loading.\n// at: 66 → when ≤66% remaining (i.e. after first ~7s of a 20s timer) → warning\n// at: 33 → when ≤33% remaining (i.e. after first ~13s) → danger\nconst thresholds = [\n    { at: 66, color: 'warning' as const },\n    { at: 33, color: 'danger' as const },\n];\n\nconst code = `// Auto color-shift: primary → warning → danger as time runs out\n// 'at' means \"when remaining % is AT OR BELOW this value\"\n<CountdownTimer\n  duration={20}\n  variant=\"circular\"\n  colorThresholds={[\n    { at: 66, color: 'warning' },  // ≤66% left → warning amber\n    { at: 33, color: 'danger' },   // ≤33% left → danger red\n  ]}\n  repeat\n/>\n\n// Static semantic colors\n<CountdownTimer duration={20} variant=\"circular\" color=\"success\" />\n<CountdownTimer duration={20} variant=\"circular\" color=\"warning\" />\n<CountdownTimer duration={20} variant=\"circular\" color=\"danger\" />\n\n// Custom hex color\n<CountdownTimer duration={20} variant=\"circular\" color=\"#8b5cf6\" />`;\n\nconst ColorThresholds: React.FC = () => (\n    <>\n        <ComponentDemo\n            title=\"Color Thresholds\"\n            description=\"Watch the auto-shift timer below — it starts primary blue, turns warning amber at ≤66% remaining, then danger red at ≤33%. Set repeat so you can observe the full cycle.\"\n            centered={false}\n        >\n            <div style={{ display: 'flex', flexWrap: 'wrap', gap: 32, padding: 16, alignItems: 'flex-start' }}>\n                <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 8 }}>\n                    <span style={{ fontSize: 11, fontWeight: 600, color: 'var(--eui-text-muted)', textTransform: 'uppercase', letterSpacing: '0.06em' }}>Auto-shift (repeat)</span>\n                    <CountdownTimer duration={20} variant=\"circular\" size=\"md\" colorThresholds={thresholds} repeat />\n                </div>\n                <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 8 }}>\n                    <span style={{ fontSize: 11, fontWeight: 600, color: 'var(--eui-text-muted)', textTransform: 'uppercase', letterSpacing: '0.06em' }}>Success</span>\n                    <CountdownTimer duration={20} variant=\"circular\" size=\"md\" color=\"success\" repeat />\n                </div>\n                <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 8 }}>\n                    <span style={{ fontSize: 11, fontWeight: 600, color: 'var(--eui-text-muted)', textTransform: 'uppercase', letterSpacing: '0.06em' }}>Warning</span>\n                    <CountdownTimer duration={20} variant=\"circular\" size=\"md\" color=\"warning\" repeat />\n                </div>\n                <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 8 }}>\n                    <span style={{ fontSize: 11, fontWeight: 600, color: 'var(--eui-text-muted)', textTransform: 'uppercase', letterSpacing: '0.06em' }}>Danger</span>\n                    <CountdownTimer duration={20} variant=\"circular\" size=\"md\" color=\"danger\" repeat />\n                </div>\n                <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 8 }}>\n                    <span style={{ fontSize: 11, fontWeight: 600, color: 'var(--eui-text-muted)', textTransform: 'uppercase', letterSpacing: '0.06em' }}>Custom #8b5cf6</span>\n                    <CountdownTimer duration={20} variant=\"circular\" size=\"md\" color=\"#8b5cf6\" repeat />\n                </div>\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default ColorThresholds;\n"
        },
        {
          "title": "CountUpMode",
          "code": "import React, { useState } from 'react';\nimport { CountdownTimer } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `// Count up from 0 → duration (elapsed timer)\n<CountdownTimer\n  duration={60}\n  variant=\"circular\"\n  countUp={true}\n  onComplete={() => alert('60 seconds elapsed!')}\n/>`;\n\nconst CountUpMode: React.FC = () => {\n    const [completed, setCompleted] = useState(false);\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Count-Up Mode\"\n                description=\"Instead of counting down, elapsed time fills up the progress from 0 to the target duration.\"\n            >\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 16 }}>\n                    <CountdownTimer\n                        duration={60}\n                        variant=\"circular\"\n                        size=\"md\"\n                        countUp\n                        onComplete={() => setCompleted(true)}\n                    />\n                    {completed && (\n                        <div\n                            style={{\n                                padding: '10px 16px',\n                                background: 'var(--eui-bg-subtle)',\n                                border: '1px solid var(--eui-border-subtle)',\n                                borderRadius: 6,\n                                fontSize: 13,\n                                color: 'var(--eui-text-muted)',\n                            }}\n                        >\n                            Target elapsed! <strong style={{ color: 'var(--eui-text)' }}>60s reached.</strong>\n                        </div>\n                    )}\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default CountUpMode;\n"
        },
        {
          "title": "DisabledState",
          "code": "import React from 'react';\nimport { CountdownTimer } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `// Disabled with default \"Off\" label\n<CountdownTimer duration={30} disabled />\n\n// Disabled with custom message\n<CountdownTimer duration={30} disabled disabledMessage=\"Unavailable\" />`;\n\nconst DisabledState: React.FC = () => (\n    <>\n        <ComponentDemo\n            title=\"Disabled State\"\n            description=\"Disable the timer entirely and show a custom badge message. All interaction is blocked.\"\n            centered={false}\n        >\n            <div style={{ display: 'flex', flexWrap: 'wrap', gap: 40, padding: 16, alignItems: 'flex-start' }}>\n                <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 8 }}>\n                    <span style={{ fontSize: 11, fontWeight: 600, color: 'var(--eui-text-muted)', textTransform: 'uppercase', letterSpacing: '0.06em' }}>Default \"Off\"</span>\n                    <CountdownTimer duration={30} variant=\"circular\" size=\"md\" disabled />\n                </div>\n                <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 8 }}>\n                    <span style={{ fontSize: 11, fontWeight: 600, color: 'var(--eui-text-muted)', textTransform: 'uppercase', letterSpacing: '0.06em' }}>Custom message</span>\n                    <CountdownTimer duration={30} variant=\"circular\" size=\"md\" disabled disabledMessage=\"Unavailable\" />\n                </div>\n                <div style={{ display: 'flex', flexDirection: 'column', gap: 8, width: '100%', maxWidth: 280 }}>\n                    <span style={{ fontSize: 11, fontWeight: 600, color: 'var(--eui-text-muted)', textTransform: 'uppercase', letterSpacing: '0.06em' }}>Linear disabled</span>\n                    <CountdownTimer duration={30} variant=\"linear\" size=\"md\" disabled disabledMessage=\"Not active\" />\n                </div>\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default DisabledState;\n"
        },
        {
          "title": "ImperativeControl",
          "code": "import React, { useRef } from 'react';\nimport { CountdownTimer } from '../../../components';\nimport type { CountdownTimerHandle } from '../../../components';\nimport { Button } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { useRef } from 'react';\nimport { CountdownTimer } from 'fluxo-ui';\nimport type { CountdownTimerHandle } from 'fluxo-ui';\n\nconst timerRef = useRef<CountdownTimerHandle>(null);\n\n<CountdownTimer ref={timerRef} duration={30} autoStart={false} showControls={false} />\n\n<button onClick={() => timerRef.current?.start()}>Start</button>\n<button onClick={() => timerRef.current?.pause()}>Pause</button>\n<button onClick={() => timerRef.current?.resume()}>Resume</button>\n<button onClick={() => timerRef.current?.reset()}>Reset</button>`;\n\nconst ImperativeControl: React.FC = () => {\n    const timerRef = useRef<CountdownTimerHandle>(null);\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Imperative Control via Ref\"\n                description=\"Expose timer controls to parent components using a forwarded ref. Hide the built-in controls and drive the timer externally.\"\n            >\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 20 }}>\n                    <CountdownTimer\n                        ref={timerRef}\n                        duration={30}\n                        variant=\"circular\"\n                        size=\"md\"\n                        autoStart={false}\n                        showControls={false}\n                    />\n                    <div\n                        style={{\n                            display: 'flex',\n                            flexWrap: 'wrap',\n                            gap: 8,\n                            justifyContent: 'center',\n                            padding: '12px 16px',\n                            background: 'var(--eui-bg-subtle)',\n                            border: '1px solid var(--eui-border-subtle)',\n                            borderRadius: 6,\n                        }}\n                    >\n                        <Button label=\"Start\" size=\"sm\" onClick={() => timerRef.current?.start()} />\n                        <Button label=\"Pause\" size=\"sm\" variant=\"secondary\" onClick={() => timerRef.current?.pause()} />\n                        <Button label=\"Resume\" size=\"sm\" variant=\"secondary\" onClick={() => timerRef.current?.resume()} />\n                        <Button label=\"Reset\" size=\"sm\" variant=\"secondary\" onClick={() => timerRef.current?.reset()} />\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default ImperativeControl;\n"
        },
        {
          "title": "LongDurations",
          "code": "import React from 'react';\nimport { CountdownTimer } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `// 2 hours = 7200 seconds → displays \"02:00 hrs\"\n<CountdownTimer duration={7200} variant=\"circular\" />\n\n// 1.5 days = 129600 seconds → displays days + hours\n<CountdownTimer duration={129600} variant=\"numeric\" />\n\n// 90 minutes = 5400 seconds → displays \"01:30 min\"\n<CountdownTimer duration={5400} variant=\"linear\" />`;\n\nconst LongDurations: React.FC = () => (\n    <>\n        <ComponentDemo\n            title=\"Long Durations\"\n            description=\"When duration exceeds 60s the display auto-promotes to minutes, hours, or days. Pass seconds only.\"\n            centered={false}\n        >\n            <div style={{ display: 'flex', flexWrap: 'wrap', gap: 40, padding: 16, alignItems: 'flex-start' }}>\n                <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 8 }}>\n                    <span style={{ fontSize: 11, fontWeight: 600, color: 'var(--eui-text-muted)', textTransform: 'uppercase', letterSpacing: '0.06em' }}>2h circular</span>\n                    <CountdownTimer duration={7200} variant=\"circular\" size=\"md\" autoStart={false} />\n                </div>\n                <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 8 }}>\n                    <span style={{ fontSize: 11, fontWeight: 600, color: 'var(--eui-text-muted)', textTransform: 'uppercase', letterSpacing: '0.06em' }}>1.5 days numeric</span>\n                    <CountdownTimer duration={129600} variant=\"numeric\" size=\"sm\" autoStart={false} />\n                </div>\n                <div style={{ display: 'flex', flexDirection: 'column', gap: 8, width: '100%', maxWidth: 300 }}>\n                    <span style={{ fontSize: 11, fontWeight: 600, color: 'var(--eui-text-muted)', textTransform: 'uppercase', letterSpacing: '0.06em' }}>90 min linear</span>\n                    <CountdownTimer duration={5400} variant=\"linear\" size=\"md\" autoStart={false} />\n                </div>\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default LongDurations;\n"
        },
        {
          "title": "PauseOnHover",
          "code": "import React from 'react';\nimport { CountdownTimer } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `// Pauses automatically while the user hovers over the timer\n<CountdownTimer\n  duration={60}\n  variant=\"circular\"\n  pauseOnHover={true}\n/>`;\n\nconst PauseOnHover: React.FC = () => (\n    <>\n        <ComponentDemo\n            title=\"Pause on Hover\"\n            description=\"Hover over the timer to pause it automatically — useful in interactive UIs where the user might need a moment.\"\n        >\n            <CountdownTimer\n                duration={60}\n                variant=\"circular\"\n                size=\"md\"\n                pauseOnHover\n            />\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default PauseOnHover;\n"
        },
        {
          "title": "RepeatAndAutoStart",
          "code": "import React from 'react';\nimport { CountdownTimer } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `// Repeat: automatically restarts when completed\n<CountdownTimer duration={15} repeat={true} />\n\n// Manual start: does not start until you press play\n<CountdownTimer duration={30} autoStart={false} />`;\n\nconst RepeatAndAutoStart: React.FC = () => (\n    <>\n        <ComponentDemo\n            title=\"Repeat & Auto-Start\"\n            description=\"Use repeat to loop infinitely on completion. Use autoStart={false} to let the user start manually.\"\n            centered={false}\n        >\n            <div style={{ display: 'flex', flexWrap: 'wrap', gap: 40, padding: 16, alignItems: 'flex-start' }}>\n                <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 8 }}>\n                    <span style={{ fontSize: 11, fontWeight: 600, color: 'var(--eui-text-muted)', textTransform: 'uppercase', letterSpacing: '0.06em' }}>Repeat (15s loop)</span>\n                    <CountdownTimer duration={15} variant=\"circular\" size=\"md\" repeat />\n                </div>\n                <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 8 }}>\n                    <span style={{ fontSize: 11, fontWeight: 600, color: 'var(--eui-text-muted)', textTransform: 'uppercase', letterSpacing: '0.06em' }}>Manual Start</span>\n                    <CountdownTimer duration={30} variant=\"circular\" size=\"md\" autoStart={false} />\n                </div>\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default RepeatAndAutoStart;\n"
        },
        {
          "title": "Sizes",
          "code": "import React from 'react';\nimport { CountdownTimer } from '../../../components';\nimport type { CountdownTimerSize } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst sizes: CountdownTimerSize[] = ['xs', 'sm', 'md', 'lg', 'xl'];\n\nconst code = `<CountdownTimer duration={60} variant=\"circular\" size=\"xs\" />\n<CountdownTimer duration={60} variant=\"circular\" size=\"sm\" />\n<CountdownTimer duration={60} variant=\"circular\" size=\"md\" />\n<CountdownTimer duration={60} variant=\"circular\" size=\"lg\" />\n<CountdownTimer duration={60} variant=\"circular\" size=\"xl\" />`;\n\nconst Sizes: React.FC = () => (\n    <>\n        <ComponentDemo\n            title=\"Sizes\"\n            description=\"Five sizes from xs to xl — applies to all variants.\"\n            centered={false}\n        >\n            <div style={{ display: 'flex', flexWrap: 'wrap', alignItems: 'flex-end', gap: 32, padding: 16 }}>\n                {sizes.map((s) => (\n                    <div key={s} style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 8 }}>\n                        <CountdownTimer duration={60} variant=\"circular\" size={s} showControls={false} />\n                        <span style={{ fontSize: 11, fontWeight: 600, color: 'var(--eui-text-muted)', textTransform: 'uppercase', letterSpacing: '0.06em' }}>{s}</span>\n                    </div>\n                ))}\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default Sizes;\n"
        },
        {
          "title": "Variants",
          "code": "import React from 'react';\nimport { CountdownTimer } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `// Circular — ring arc progress\n<CountdownTimer duration={60} variant=\"circular\" />\n\n// Rounded Square — rounded rectangle border progress\n<CountdownTimer duration={60} variant=\"rounded-square\" />\n\n// Triangle — equilateral triangle border progress\n<CountdownTimer duration={60} variant=\"triangle\" />\n\n// Linear — horizontal bar progress\n<CountdownTimer duration={60} variant=\"linear\" />\n\n// Segmented — equal blocks that disappear one by one\n<CountdownTimer duration={60} variant=\"segmented\" segmentCount={20} />\n\n// Numeric — styled digit display\n<CountdownTimer duration={3723} variant=\"numeric\" />`;\n\nconst shapeVariants = [\n    { key: 'circular', label: 'Circular' },\n    { key: 'rounded-square', label: 'Rounded Square' },\n    { key: 'triangle', label: 'Triangle' },\n] as const;\n\n\nconst Variants: React.FC = () => (\n    <>\n        <ComponentDemo\n            title=\"Shape Variants\"\n            description=\"Three SVG border-progress shapes: circular ring, rounded square, and equilateral triangle.\"\n            centered={false}\n        >\n            <div style={{ display: 'flex', flexWrap: 'wrap', gap: 40, padding: 16, alignItems: 'flex-end', justifyContent: 'center' }}>\n                {shapeVariants.map(({ key, label }) => (\n                    <div key={key} style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 10 }}>\n                        <span style={{ fontSize: 12, fontWeight: 600, color: 'var(--eui-text-muted)', textTransform: 'uppercase', letterSpacing: '0.06em' }}>{label}</span>\n                        <CountdownTimer duration={60} variant={key} size=\"md\" />\n                    </div>\n                ))}\n            </div>\n        </ComponentDemo>\n\n        <ComponentDemo\n            title=\"Other Variants\"\n            description=\"Linear bar, segmented blocks, and large numeric digit display.\"\n            centered={false}\n        >\n            <div style={{ display: 'flex', flexDirection: 'column', gap: 32, padding: 16 }}>\n                <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>\n                    <span style={{ fontSize: 12, fontWeight: 600, color: 'var(--eui-text-muted)', textTransform: 'uppercase', letterSpacing: '0.06em' }}>Linear</span>\n                    <CountdownTimer duration={60} variant=\"linear\" size=\"md\" />\n                </div>\n                <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-start', gap: 8 }}>\n                    <span style={{ fontSize: 12, fontWeight: 600, color: 'var(--eui-text-muted)', textTransform: 'uppercase', letterSpacing: '0.06em' }}>Segmented (20 blocks, single uniform row)</span>\n                    <CountdownTimer duration={60} variant=\"segmented\" size=\"md\" segmentCount={20} />\n                </div>\n                <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-start', gap: 8 }}>\n                    <span style={{ fontSize: 12, fontWeight: 600, color: 'var(--eui-text-muted)', textTransform: 'uppercase', letterSpacing: '0.06em' }}>Numeric</span>\n                    <CountdownTimer duration={3723} variant=\"numeric\" size=\"md\" />\n                </div>\n            </div>\n        </ComponentDemo>\n\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default Variants;\n"
        }
      ],
      "props": {
        "timerProps": {
          "duration": {
            "type": "number",
            "required": true,
            "description": "Total duration in seconds."
          },
          "variant": {
            "type": "'circular' | 'rounded-square' | 'triangle' | 'linear' | 'segmented' | 'numeric'",
            "default": "'circular'",
            "description": "Visual display style."
          },
          "size": {
            "type": "'xs' | 'sm' | 'md' | 'lg' | 'xl'",
            "default": "'md'",
            "description": "Size of the timer control."
          },
          "autoStart": {
            "type": "boolean",
            "default": true,
            "description": "Start the timer immediately on mount."
          },
          "repeat": {
            "type": "boolean",
            "default": false,
            "description": "Automatically restart when completed."
          },
          "countUp": {
            "type": "boolean",
            "default": false,
            "description": "Count up from 0 to duration instead of counting down."
          },
          "color": {
            "type": "'primary' | 'success' | 'warning' | 'danger' | string",
            "default": "'primary'",
            "description": "Static color for the progress indicator. Accepts semantic names or any CSS color."
          },
          "colorThresholds": {
            "type": "ColorThreshold[]",
            "description": "Array of { at: number (%), color } breakpoints for auto color-shifting."
          },
          "segmentCount": {
            "type": "number",
            "default": 20,
            "description": "Number of segments for the segmented variant."
          },
          "showControls": {
            "type": "boolean",
            "default": true,
            "description": "Show the built-in pause and reset buttons."
          },
          "pauseOnHover": {
            "type": "boolean",
            "default": false,
            "description": "Automatically pause when the user hovers over the timer."
          },
          "disabled": {
            "type": "boolean",
            "default": false,
            "description": "Disable the timer — no interaction, shows disabled badge."
          },
          "disabledMessage": {
            "type": "string",
            "default": "'Off'",
            "description": "Badge text shown when disabled."
          },
          "pulseWhenRunning": {
            "type": "boolean",
            "default": false,
            "description": "Apply a subtle pulse animation to the time display while running."
          },
          "announceInterval": {
            "type": "number",
            "description": "Announce the remaining time via aria-live region every N seconds (e.g. 60 for once-per-minute)."
          },
          "announceFinalSeconds": {
            "type": "number",
            "description": "When remaining seconds drops to or below this value, announce every second via aria-live (e.g. 10 for the final ten-second countdown)."
          },
          "announceOnComplete": {
            "type": "boolean",
            "default": false,
            "description": "Announce 'Timer complete' via aria-live region when the timer reaches zero."
          },
          "announcePoliteness": {
            "type": "'polite' | 'assertive'",
            "default": "'polite'",
            "description": "aria-live politeness for the announcement region."
          },
          "criticalThreshold": {
            "type": "number",
            "description": "Fire onCriticalThreshold once when remaining seconds first drops to or below this value."
          },
          "onCriticalThreshold": {
            "type": "(remaining: number) => void",
            "description": "Called the first time remaining time crosses criticalThreshold (resets on reset/restart)."
          },
          "className": {
            "type": "string",
            "description": "Additional CSS class name."
          },
          "style": {
            "type": "React.CSSProperties",
            "description": "Inline style override."
          },
          "onComplete": {
            "type": "() => void",
            "description": "Called when the timer reaches zero (or duration in count-up mode)."
          },
          "onTick": {
            "type": "(remaining: number, elapsed: number) => void",
            "description": "Called every second with remaining and elapsed values."
          },
          "onPause": {
            "type": "(remaining: number) => void",
            "description": "Called when the timer is paused."
          },
          "onResume": {
            "type": "(remaining: number) => void",
            "description": "Called when the timer resumes."
          },
          "onReset": {
            "type": "() => void",
            "description": "Called when the timer is reset."
          }
        },
        "handleProps": {
          "start()": {
            "type": "function",
            "description": "Start the timer if not already running."
          },
          "pause()": {
            "type": "function",
            "description": "Pause the timer."
          },
          "resume()": {
            "type": "function",
            "description": "Resume a paused timer."
          },
          "reset()": {
            "type": "function",
            "description": "Reset to initial value. Restarts automatically if autoStart is true."
          }
        }
      },
      "storyDir": "countdown-timer"
    },
    "DashboardLayout": {
      "name": "DashboardLayout",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React, { useMemo } from 'react';\nimport { DashboardLayout } from '../../../components/dashboard-layout';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { buildDemoWidgets, demoDefaultLayouts } from './dashboard-story-data';\n\nconst code = `import { DashboardLayout } from 'fluxo-ui';\nimport type { DashboardWidget, DashboardLayouts } from 'fluxo-ui';\n\nconst widgets: DashboardWidget[] = [\n  { id: 'sales',    title: 'Sales',    icon: LineChartUpIcon, children: <Sales /> },\n  { id: 'visitors', title: 'Visitors', icon: UsersIcon,       children: <Visitors /> },\n  { id: 'channels', title: 'Channels', icon: PieChartIcon,    children: <Channels /> },\n  // ...\n];\n\nconst defaultLayouts: DashboardLayouts = {\n  lg: [\n    { id: 'sales',    x: 0, y: 0, w: 4, h: 4 },\n    { id: 'visitors', x: 4, y: 0, w: 4, h: 4 },\n    { id: 'channels', x: 8, y: 0, w: 4, h: 4 },\n    // ...\n  ],\n};\n\n<DashboardLayout\n  widgets={widgets}\n  defaultLayouts={defaultLayouts}\n  toolbarTitle=\"Overview\"\n/>`;\n\nconst BasicUsage: React.FC = () => {\n    const widgets = useMemo(() => buildDemoWidgets(), []);\n\n    return (\n        <ComponentDemo\n            title=\"Basic Dashboard\"\n            description=\"Click 'Edit layout' to drag widget headers, resize from the corners, and toggle visibility. Use the maximize / collapse buttons on each widget for focused views.\"\n            centered={false}\n        >\n            <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16 }}>\n                <div\n                    style={{\n                        minHeight: 600,\n                        background: 'var(--eui-bg)',\n                        border: '1px solid var(--eui-border-subtle)',\n                        borderRadius: 8,\n                        padding: 12,\n                    }}\n                >\n                    <DashboardLayout\n                        widgets={widgets}\n                        defaultLayouts={demoDefaultLayouts}\n                        toolbarTitle=\"Overview\"\n                        rowHeight={48}\n                    />\n                </div>\n                <CodeBlock code={code} />\n            </div>\n        </ComponentDemo>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "Persistence",
          "code": "import React, { useMemo } from 'react';\nimport { DashboardLayout } from '../../../components/dashboard-layout';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { buildDemoWidgets, demoDefaultLayouts } from './dashboard-story-data';\n\nconst code = `<DashboardLayout\n  widgets={widgets}\n  defaultLayouts={defaultLayouts}\n  persistKey=\"my-app-dashboard\"\n  toolbarTitle=\"My Dashboard\"\n/>`;\n\nconst Persistence: React.FC = () => {\n    const widgets = useMemo(() => buildDemoWidgets(), []);\n\n    return (\n        <ComponentDemo\n            title=\"LocalStorage Persistence\"\n            description=\"Pass a persistKey and the full DashboardLayoutState (layouts, hidden, collapsed, maximized, preset) is saved automatically. Drag a widget, refresh the page, and watch it come back.\"\n            centered={false}\n        >\n            <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16 }}>\n                <div\n                    style={{\n                        minHeight: 540,\n                        background: 'var(--eui-bg)',\n                        border: '1px solid var(--eui-border-subtle)',\n                        borderRadius: 8,\n                        padding: 12,\n                    }}\n                >\n                    <DashboardLayout\n                        widgets={widgets}\n                        defaultLayouts={demoDefaultLayouts}\n                        toolbarTitle=\"My Dashboard\"\n                        persistKey=\"fluxo-dashboard-demo\"\n                        rowHeight={48}\n                    />\n                </div>\n                <div\n                    style={{\n                        padding: '10px 14px',\n                        background: 'var(--eui-bg-subtle)',\n                        border: '1px solid var(--eui-border-subtle)',\n                        borderRadius: 6,\n                        fontSize: 12,\n                        color: 'var(--eui-text-muted)',\n                    }}\n                >\n                    Saved to <code style={{ color: 'var(--eui-text)' }}>localStorage[\"fluxo-dashboard-demo\"]</code>. Use the Reset\n                    button in the toolbar to restore defaults.\n                </div>\n                <CodeBlock code={code} />\n            </div>\n        </ComponentDemo>\n    );\n};\n\nexport default Persistence;\n"
        },
        {
          "title": "Presets",
          "code": "import React, { useMemo } from 'react';\nimport { DashboardLayout } from '../../../components/dashboard-layout';\nimport type { DashboardLayoutPreset } from '../../../components/dashboard-layout';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { buildDemoWidgets, demoDefaultLayouts } from './dashboard-story-data';\n\nconst code = `const presets: DashboardLayoutPreset[] = [\n  {\n    id: 'default',\n    name: 'Default',\n    description: 'Balanced overview',\n    layouts: defaultLayouts,\n  },\n  {\n    id: 'sales-focus',\n    name: 'Sales focus',\n    description: 'Pin sales + orders, hide others',\n    hiddenIds: ['channels', 'team', 'health', 'calendar'],\n    layouts: {\n      lg: [\n        { id: 'sales',    x: 0, y: 0, w: 6, h: 6 },\n        { id: 'orders',   x: 6, y: 0, w: 6, h: 6 },\n        { id: 'visitors', x: 0, y: 6, w: 12, h: 5 },\n      ],\n    },\n  },\n];\n\n<DashboardLayout widgets={widgets} presets={presets} ... />`;\n\nconst presets: DashboardLayoutPreset[] = [\n    {\n        id: 'default',\n        name: 'Default',\n        description: 'Balanced overview',\n        layouts: demoDefaultLayouts,\n    },\n    {\n        id: 'sales-focus',\n        name: 'Sales focus',\n        description: 'Pin sales + orders, hide other widgets',\n        hiddenIds: ['channels', 'team', 'health', 'calendar'],\n        layouts: {\n            lg: [\n                { id: 'sales', x: 0, y: 0, w: 6, h: 6 },\n                { id: 'orders', x: 6, y: 0, w: 6, h: 6 },\n                { id: 'visitors', x: 0, y: 6, w: 12, h: 5 },\n            ],\n        },\n    },\n    {\n        id: 'ops',\n        name: 'Operations',\n        description: 'Team, health, calendar',\n        hiddenIds: ['sales', 'orders', 'channels'],\n        layouts: {\n            lg: [\n                { id: 'team', x: 0, y: 0, w: 4, h: 6 },\n                { id: 'health', x: 4, y: 0, w: 4, h: 6 },\n                { id: 'calendar', x: 8, y: 0, w: 4, h: 6 },\n                { id: 'visitors', x: 0, y: 6, w: 12, h: 5 },\n            ],\n        },\n    },\n];\n\nconst Presets: React.FC = () => {\n    const widgets = useMemo(() => buildDemoWidgets(), []);\n\n    return (\n        <ComponentDemo\n            title=\"Layout Presets\"\n            description=\"Define named layouts (e.g. 'Sales focus', 'Operations'). Users pick from the Presets menu. Each preset can override visibility AND positions.\"\n            centered={false}\n        >\n            <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16 }}>\n                <div\n                    style={{\n                        minHeight: 540,\n                        background: 'var(--eui-bg)',\n                        border: '1px solid var(--eui-border-subtle)',\n                        borderRadius: 8,\n                        padding: 12,\n                    }}\n                >\n                    <DashboardLayout\n                        widgets={widgets}\n                        defaultLayouts={demoDefaultLayouts}\n                        toolbarTitle=\"Presets\"\n                        presets={presets}\n                        rowHeight={48}\n                    />\n                </div>\n                <CodeBlock code={code} />\n            </div>\n        </ComponentDemo>\n    );\n};\n\nexport default Presets;\n"
        },
        {
          "title": "WidgetVariants",
          "code": "import React, { useMemo } from 'react';\nimport { DashboardLayout } from '../../../components/dashboard-layout';\nimport type { DashboardLayouts, DashboardWidget } from '../../../components/dashboard-layout';\nimport { BarChartIcon, LineChartUpIcon, PieChartIcon, UsersIcon } from '../../../assets/icons';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `const widgets: DashboardWidget[] = [\n  { id: 'a', title: 'Card chrome',       chrome: 'card',       children: <Demo /> },\n  { id: 'b', title: 'Borderless chrome', chrome: 'borderless', children: <Demo /> },\n  { id: 'c', title: 'Sunken chrome',     chrome: 'sunken',     children: <Demo /> },\n  { id: 'd', title: 'Plain chrome',      chrome: 'plain',      children: <Demo /> },\n  { id: 'e', title: 'With badge',  badge: <span>NEW</span>, children: <Demo /> },\n  { id: 'f', title: 'With error',  error: 'Service unavailable', children: <Demo /> },\n];`;\n\nconst SampleBody: React.FC<{ label: string }> = ({ label }) => (\n    <div\n        style={{\n            height: '100%',\n            display: 'flex',\n            alignItems: 'center',\n            justifyContent: 'center',\n            color: 'var(--eui-text-muted)',\n            fontSize: 13,\n        }}\n    >\n        {label}\n    </div>\n);\n\nconst layouts: DashboardLayouts = {\n    lg: [\n        { id: 'a', x: 0, y: 0, w: 4, h: 3 },\n        { id: 'b', x: 4, y: 0, w: 4, h: 3 },\n        { id: 'c', x: 8, y: 0, w: 4, h: 3 },\n        { id: 'd', x: 0, y: 3, w: 4, h: 3 },\n        { id: 'e', x: 4, y: 3, w: 4, h: 3 },\n        { id: 'f', x: 8, y: 3, w: 4, h: 3 },\n    ],\n};\n\nconst WidgetVariants: React.FC = () => {\n    const widgets = useMemo<DashboardWidget[]>(\n        () => [\n            { id: 'a', title: 'Card chrome', icon: LineChartUpIcon, chrome: 'card', children: <SampleBody label=\"card\" /> },\n            { id: 'b', title: 'Borderless', icon: UsersIcon, chrome: 'borderless', children: <SampleBody label=\"borderless\" /> },\n            { id: 'c', title: 'Sunken', icon: PieChartIcon, chrome: 'sunken', children: <SampleBody label=\"sunken\" /> },\n            { id: 'd', title: 'Plain', icon: BarChartIcon, chrome: 'plain', children: <SampleBody label=\"plain (no chrome)\" /> },\n            {\n                id: 'e',\n                title: 'With badge',\n                icon: LineChartUpIcon,\n                badge: (\n                    <span style={{ background: '#10b981', color: '#fff', padding: '0 6px', borderRadius: 9999, fontSize: 10 }}>NEW</span>\n                ),\n                children: <SampleBody label=\"Pill rendered next to the title\" />,\n            },\n            {\n                id: 'f',\n                title: 'With error',\n                icon: BarChartIcon,\n                error: 'Service unavailable — retry in 30s',\n                children: <SampleBody label=\"(hidden — error in place)\" />,\n            },\n        ],\n        [],\n    );\n\n    return (\n        <ComponentDemo\n            title=\"Widget Chrome & States\"\n            description=\"Each widget can pick its visual chrome and surface badges, errors, and loading states without extra wiring.\"\n            centered={false}\n        >\n            <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16 }}>\n                <div\n                    style={{\n                        minHeight: 420,\n                        background: 'var(--eui-bg)',\n                        border: '1px solid var(--eui-border-subtle)',\n                        borderRadius: 8,\n                        padding: 12,\n                    }}\n                >\n                    <DashboardLayout widgets={widgets} defaultLayouts={layouts} toolbarTitle=\"Chrome variants\" rowHeight={48} />\n                </div>\n                <CodeBlock code={code} />\n            </div>\n        </ComponentDemo>\n    );\n};\n\nexport default WidgetVariants;\n"
        },
        {
          "title": "WithSettings",
          "code": "import React, { useMemo } from 'react';\nimport { DashboardLayout } from '../../../components/dashboard-layout';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { buildDemoWidgets, demoDefaultLayouts } from './dashboard-story-data';\n\nconst code = `const widgets: DashboardWidget[] = [\n  {\n    id: 'sales',\n    title: 'Sales',\n    renderSettings: ({ closeSettings }) => (\n      <>\n        <label><input type=\"checkbox\" /> Compare to prev period</label>\n        <button onClick={closeSettings}>Save</button>\n      </>\n    ),\n    onRefresh: async () => {\n      await fetch('/api/sales').then(/*...*/);\n    },\n    children: <Sales />,\n  },\n];`;\n\nconst WithSettings: React.FC = () => {\n    const widgets = useMemo(() => buildDemoWidgets({ withSettings: true }), []);\n\n    return (\n        <ComponentDemo\n            title=\"Per-widget Refresh & Settings\"\n            description=\"Hand each widget an onRefresh handler to enable the refresh icon (the icon spins while the promise resolves) and a renderSettings function to expose a settings popover.\"\n            centered={false}\n        >\n            <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16 }}>\n                <div\n                    style={{\n                        minHeight: 540,\n                        background: 'var(--eui-bg)',\n                        border: '1px solid var(--eui-border-subtle)',\n                        borderRadius: 8,\n                        padding: 12,\n                    }}\n                >\n                    <DashboardLayout\n                        widgets={widgets}\n                        defaultLayouts={demoDefaultLayouts}\n                        toolbarTitle=\"With Settings\"\n                        rowHeight={48}\n                    />\n                </div>\n                <CodeBlock code={code} />\n            </div>\n        </ComponentDemo>\n    );\n};\n\nexport default WithSettings;\n"
        }
      ],
      "props": {
        "dashboardLayoutProps": {
          "widgets": {
            "type": "DashboardWidget[]",
            "required": true,
            "description": "All widgets that can appear on the dashboard. Hidden ones are listed in the Add Widget panel."
          },
          "layouts": {
            "type": "DashboardLayouts",
            "description": "Controlled per-breakpoint layouts: { lg: WidgetLayout[], md: ..., ... }. Pair with onLayoutChange."
          },
          "defaultLayouts": {
            "type": "DashboardLayouts",
            "description": "Initial per-breakpoint layouts (uncontrolled). Auto-generated if omitted."
          },
          "onLayoutChange": {
            "type": "(payload: DashboardLayoutChangePayload) => void",
            "description": "Fires on every layout, visibility, collapse, maximize, preset or reset change."
          },
          "breakpoints": {
            "type": "DashboardBreakpoint[]",
            "default": "xl/lg/md/sm/xs",
            "description": "Custom breakpoint definitions: { key, minWidth, columns, label? }."
          },
          "rowHeight": {
            "type": "number",
            "default": "64",
            "description": "Pixel height of one grid row."
          },
          "margin": {
            "type": "[number, number]",
            "default": "[12, 12]",
            "description": "Horizontal and vertical gap between widgets in pixels."
          },
          "containerPadding": {
            "type": "[number, number]",
            "default": "[12, 12]",
            "description": "Padding inside the grid container in pixels."
          },
          "minWidgetWidth": {
            "type": "number",
            "default": "1",
            "description": "Minimum column span for any widget."
          },
          "minWidgetHeight": {
            "type": "number",
            "default": "1",
            "description": "Minimum row span for any widget."
          },
          "editMode": {
            "type": "boolean",
            "description": "Controlled edit mode. When true, drag/resize handles and toolbar actions are enabled."
          },
          "defaultEditMode": {
            "type": "boolean",
            "default": "false",
            "description": "Initial edit mode (uncontrolled)."
          },
          "onEditModeChange": {
            "type": "(editing: boolean) => void",
            "description": "Fires when the user toggles edit mode."
          },
          "persistKey": {
            "type": "string",
            "description": "localStorage key for automatic save/restore of the full DashboardLayoutState."
          },
          "presets": {
            "type": "DashboardLayoutPreset[]",
            "description": "Named layout presets to expose in the toolbar Presets menu."
          },
          "onPresetChange": {
            "type": "(preset: DashboardLayoutPreset | null) => void",
            "description": "Fires when the user selects a preset."
          },
          "showToolbar": {
            "type": "boolean",
            "default": "true",
            "description": "Show the built-in toolbar (Edit, Add Widget, Reset, Presets)."
          },
          "toolbarTitle": {
            "type": "string",
            "description": "Title rendered on the left of the toolbar (also used as the grid's aria-label)."
          },
          "toolbarSlotStart": {
            "type": "React.ReactNode",
            "description": "Custom content rendered after the toolbar title."
          },
          "toolbarSlotEnd": {
            "type": "React.ReactNode",
            "description": "Custom content rendered before the Edit button on the right side of the toolbar."
          },
          "addWidgetLabel": {
            "type": "string",
            "description": "Override the Add Widget button label."
          },
          "compactType": {
            "type": "'vertical' | 'horizontal' | null",
            "default": "'vertical'",
            "description": "Auto-compaction direction after drag/resize. null disables compaction."
          },
          "allowOverlap": {
            "type": "boolean",
            "default": "false",
            "description": "Allow widgets to overlap (skip collision push-down)."
          },
          "emptyState": {
            "type": "React.ReactNode",
            "description": "Custom empty state when there are no visible widgets."
          },
          "locale": {
            "type": "Partial<DashboardLayoutLocale>",
            "description": "Override any built-in toolbar / action label."
          },
          "className": {
            "type": "string",
            "description": "Class name applied to the outer wrapper."
          },
          "style": {
            "type": "React.CSSProperties",
            "description": "Inline styles for the outer wrapper."
          },
          "widgetClassName": {
            "type": "string",
            "description": "Class name applied to every widget surface."
          }
        },
        "dashboardWidgetProps": {
          "id": {
            "type": "string",
            "required": true,
            "description": "Unique widget id; referenced by layouts and presets."
          },
          "title": {
            "type": "string",
            "required": true,
            "description": "Widget title shown in the header bar and Add Widget panel."
          },
          "icon": {
            "type": "SVGIcon",
            "description": "Optional header icon (from fluxo-ui/icons)."
          },
          "description": {
            "type": "string",
            "description": "Short description shown in the Add Widget panel."
          },
          "category": {
            "type": "string",
            "description": "Optional grouping label for future categorization."
          },
          "chrome": {
            "type": "'card' | 'plain' | 'borderless' | 'sunken'",
            "default": "'card'",
            "description": "Visual chrome around the widget."
          },
          "headerActions": {
            "type": "React.ReactNode",
            "description": "Custom icons / buttons / dropdowns rendered to the left of the built-in widget actions (refresh, settings, collapse, maximize, remove). Wrap them in elements with class `eui-dashboard-widget-action` to inherit the built-in button styling, or use your own controls. Pointer events inside this slot do not trigger drag."
          },
          "renderSettings": {
            "type": "(ctx: WidgetSettingsContext) => React.ReactNode",
            "description": "Render-prop for the per-widget settings popover. Setting this enables the gear icon."
          },
          "onRefresh": {
            "type": "() => void | Promise<void>",
            "description": "Setting this enables the refresh icon. While the promise is pending the icon spins."
          },
          "loading": {
            "type": "boolean",
            "description": "Force the loading overlay independent of refresh state."
          },
          "error": {
            "type": "string | null",
            "description": "Display an error block in place of the body content."
          },
          "lastUpdated": {
            "type": "Date | string | number",
            "description": "Shown in the widget footer as 'Updated: …'."
          },
          "badge": {
            "type": "React.ReactNode",
            "description": "Pill rendered next to the widget title."
          },
          "defaultCollapsed": {
            "type": "boolean",
            "default": "false",
            "description": "Start with the body collapsed to just the header."
          },
          "hidden": {
            "type": "boolean",
            "default": "false",
            "description": "Initial visibility. Hidden widgets appear in the Add Widget panel."
          },
          "canDrag": {
            "type": "boolean",
            "default": "true",
            "description": "Allow the user to drag this widget."
          },
          "canResize": {
            "type": "boolean",
            "default": "true",
            "description": "Allow the user to resize this widget."
          },
          "canRemove": {
            "type": "boolean",
            "default": "true",
            "description": "Allow the user to hide this widget."
          },
          "canCollapse": {
            "type": "boolean",
            "default": "true",
            "description": "Allow the user to collapse this widget."
          },
          "canMaximize": {
            "type": "boolean",
            "default": "true",
            "description": "Allow the user to maximize this widget."
          },
          "children": {
            "type": "React.ReactNode",
            "required": true,
            "description": "Widget body content."
          }
        }
      },
      "storyDir": "dashboard-layout"
    },
    "DateRangePicker": {
      "name": "DateRangePicker",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React, { useState } from 'react';\nimport { DateRangePicker } from '../../../components';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst BasicUsage: React.FC = () => {\n    const [basicRange, setBasicRange] = useState<[Date, Date] | null>(null);\n\n    return (\n        <ComponentDemo title=\"Basic Date Range Picker\" description=\"Simple date range selection\">\n            <div className=\"w-full max-w-80\">\n                <DateRangePicker\n                    value={basicRange || undefined}\n                    placeholder=\"Select date range...\"\n                    onChange={(selection) => setBasicRange(selection.value)}\n                />\n            </div>\n        </ComponentDemo>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "Constraints",
          "code": "import React, { useState } from 'react';\nimport { DateRangePicker } from '../../../components';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst Constraints: React.FC = () => {\n    const [presetRange, setPresetRange] = useState<[Date, Date]>([new Date(), new Date(Date.now() + 7 * 24 * 60 * 60 * 1000)]);\n\n    return (\n        <ComponentDemo title=\"With Constraints\" description=\"Limited to future dates only\">\n            <div className=\"w-full max-w-80\">\n                <DateRangePicker\n                    value={presetRange}\n                    minDate={new Date()}\n                    onChange={(selection) => setPresetRange(selection.value)}\n                />\n            </div>\n        </ComponentDemo>\n    );\n};\n\nexport default Constraints;\n"
        },
        {
          "title": "CustomFormat",
          "code": "import React, { useState } from 'react';\nimport { DateRangePicker } from '../../../components';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst CustomFormat: React.FC = () => {\n    const [presetRange, setPresetRange] = useState<[Date, Date]>([new Date(), new Date(Date.now() + 7 * 24 * 60 * 60 * 1000)]);\n\n    return (\n        <ComponentDemo title=\"Custom Format\" description=\"Custom date format and separator\">\n            <div className=\"w-full max-w-80\">\n                <DateRangePicker\n                    value={presetRange}\n                    dateFormat=\"yyyy-MM-dd\"\n                    separator=\" to \"\n                    onChange={(selection) => setPresetRange(selection.value)}\n                />\n            </div>\n        </ComponentDemo>\n    );\n};\n\nexport default CustomFormat;\n"
        },
        {
          "title": "DisabledState",
          "code": "import React, { useState } from 'react';\nimport { DateRangePicker } from '../../../components';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst DisabledState: React.FC = () => {\n    const [presetRange] = useState<[Date, Date]>([new Date(), new Date(Date.now() + 7 * 24 * 60 * 60 * 1000)]);\n\n    return (\n        <ComponentDemo title=\"Disabled State\" description=\"DateRangePicker in disabled state\">\n            <div className=\"w-full max-w-80\">\n                <DateRangePicker\n                    value={presetRange}\n                    disabled\n                    onChange={() => {}}\n                />\n            </div>\n        </ComponentDemo>\n    );\n};\n\nexport default DisabledState;\n"
        },
        {
          "title": "FirstDayOfWeek",
          "code": "import React, { useState } from 'react';\nimport { DateRangePicker, Dropdown } from '../../../components';\nimport type { DateRangeValue } from '../../../components';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { CodeBlock } from '../../CodeBlock';\n\nconst firstDayCode = `<DateRangePicker\n  firstDayOfWeek={1} // Monday\n  onChange={(sel) => console.log(sel.value)}\n/>`;\n\nconst dayOptions = [\n    { label: 'Sunday', value: 0 },\n    { label: 'Monday', value: 1 },\n    { label: 'Tuesday', value: 2 },\n    { label: 'Saturday', value: 6 },\n];\n\nconst FirstDayOfWeek: React.FC = () => {\n    const [range, setRange] = useState<DateRangeValue | null>(null);\n    const [firstDay, setFirstDay] = useState(0);\n\n    return (\n        <>\n            <ComponentDemo title=\"First Day of Week\" description=\"Configure which day the calendar week starts on.\" centered={false}>\n                <div className=\"flex flex-wrap items-end gap-4\">\n                    <div className=\"space-y-2\">\n                        <label className=\"text-xs font-semibold text-gray-500 uppercase tracking-wide\">Start day</label>\n                        <Dropdown\n                            value={firstDay}\n                            options={dayOptions}\n                            onChange={(e) => setFirstDay(e.value)}\n                            size=\"sm\"\n                        />\n                    </div>\n                    <div className=\"space-y-2\">\n                        <label className=\"text-xs font-semibold text-gray-500 uppercase tracking-wide\">Week Picker</label>\n                        <div className=\"w-full max-w-80\">\n                            <DateRangePicker\n                                value={range || undefined}\n                                placeholder=\"Select a week...\"\n                                selectionMode=\"week\"\n                                firstDayOfWeek={firstDay}\n                                onChange={(sel) => setRange(sel.value)}\n                            />\n                        </div>\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={firstDayCode} title=\"First Day of Week\" />\n            </div>\n        </>\n    );\n};\n\nexport default FirstDayOfWeek;\n"
        },
        {
          "title": "PositionDemo",
          "code": "import React, { useState } from 'react';\nimport { DateRangePicker } from '../../../components';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst PositionDemo: React.FC = () => {\n    const [topRange, setTopRange] = useState<[Date, Date]>([new Date(), new Date(Date.now() + 3 * 24 * 60 * 60 * 1000)]);\n\n    return (\n        <ComponentDemo title=\"Popover Position — Top\" description=\"Picker opens upward using topStart position\">\n            <div className=\"w-full max-w-80 mt-32\">\n                <DateRangePicker\n                    value={topRange}\n                    position=\"topStart\"\n                    onChange={(selection) => setTopRange(selection.value)}\n                />\n            </div>\n        </ComponentDemo>\n    );\n};\n\nexport default PositionDemo;\n"
        },
        {
          "title": "PresetDates",
          "code": "import React, { useState } from 'react';\nimport { DateRangePicker } from '../../../components';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst PresetDates: React.FC = () => {\n    const [presetRange, setPresetRange] = useState<[Date, Date]>([new Date(), new Date(Date.now() + 7 * 24 * 60 * 60 * 1000)]);\n\n    return (\n        <ComponentDemo title=\"With Preset Dates\" description=\"Date range picker with preset values\">\n            <div className=\"w-full max-w-80\">\n                <DateRangePicker\n                    value={presetRange}\n                    placeholder=\"Modify date range...\"\n                    onChange={(selection) => setPresetRange(selection.value)}\n                />\n            </div>\n        </ComponentDemo>\n    );\n};\n\nexport default PresetDates;\n"
        },
        {
          "title": "QuickSelect",
          "code": "import React, { useState } from 'react';\nimport { DateRangePicker } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { quickRanges, quickSelectCode } from './date-range-picker-story-data';\n\nconst QuickSelect: React.FC = () => {\n    const [quickSelectRange, setQuickSelectRange] = useState<string>('today');\n    const [, setPresetRange] = useState<[Date, Date]>([new Date(), new Date(Date.now() + 7 * 24 * 60 * 60 * 1000)]);\n\n    return (\n        <>\n            <ComponentDemo title=\"With Quick Select Ranges\" description=\"Date range picker with predefined quick ranges\">\n                <div className=\"w-full max-w-80\">\n                    <DateRangePicker\n                        value={quickSelectRange}\n                        ranges={quickRanges}\n                        onChange={(selection) => {\n                            setQuickSelectRange(String(selection.range || 'custom'));\n                            if (Array.isArray(selection.value)) {\n                                setPresetRange(selection.value);\n                            }\n                        }}\n                    />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={quickSelectCode} language=\"typescript\" />\n            </div>\n        </>\n    );\n};\n\nexport default QuickSelect;\n"
        },
        {
          "title": "SelectionModes",
          "code": "import React, { useState } from 'react';\nimport { DateRangePicker } from '../../../components';\nimport type { DateRangeValue } from '../../../components';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { CodeBlock } from '../../CodeBlock';\n\nconst selectionModeCode = `<DateRangePicker\n  selectionMode=\"week\"\n  range={false}\n  firstDayOfWeek={1}\n  onChange={(sel) => console.log(sel.value)}\n/>\n\n<DateRangePicker\n  selectionMode=\"month\"\n  range={false}\n  onChange={(sel) => console.log(sel.value)}\n/>\n\n<DateRangePicker\n  selectionMode=\"year\"\n  range={false}\n  onChange={(sel) => console.log(sel.value)}\n/>`;\n\nconst SelectionModes: React.FC = () => {\n    const [weekRange, setWeekRange] = useState<DateRangeValue | null>(null);\n    const [monthRange, setMonthRange] = useState<DateRangeValue | null>(null);\n    const [yearRange, setYearRange] = useState<DateRangeValue | null>(null);\n    const [dayRange, setDayRange] = useState<DateRangeValue | null>(null);\n\n    const formatRange = (range: DateRangeValue | null) => {\n        if (!range) return 'None selected';\n        return `${range[0].toLocaleDateString()} – ${range[1].toLocaleDateString()}`;\n    };\n\n    return (\n        <>\n            <ComponentDemo title=\"Selection Modes\" description=\"Control what unit is selected: day (default), week, month, or year.\" centered={false}>\n                <div className=\"grid grid-cols-1 md:grid-cols-2 gap-6\">\n                    <div className=\"space-y-2\">\n                        <label className=\"text-xs font-semibold text-gray-500 uppercase tracking-wide\">Day Mode (default)</label>\n                        <div className=\"w-full max-w-80\">\n                            <DateRangePicker\n                                value={dayRange || undefined}\n                                placeholder=\"Select day range...\"\n                                onChange={(sel) => setDayRange(sel.value)}\n                            />\n                        </div>\n                        <p className=\"text-xs text-gray-400\">{formatRange(dayRange)}</p>\n                    </div>\n                    <div className=\"space-y-2\">\n                        <label className=\"text-xs font-semibold text-gray-500 uppercase tracking-wide\">Week Mode</label>\n                        <div className=\"w-full max-w-80\">\n                            <DateRangePicker\n                                value={weekRange || undefined}\n                                placeholder=\"Select a week...\"\n                                selectionMode=\"week\"\n                                range={false}\n                                onChange={(sel) => setWeekRange(sel.value)}\n                            />\n                        </div>\n                        <p className=\"text-xs text-gray-400\">{formatRange(weekRange)}</p>\n                    </div>\n                    <div className=\"space-y-2\">\n                        <label className=\"text-xs font-semibold text-gray-500 uppercase tracking-wide\">Month Mode</label>\n                        <div className=\"w-full max-w-80\">\n                            <DateRangePicker\n                                value={monthRange || undefined}\n                                placeholder=\"Select a month...\"\n                                selectionMode=\"month\"\n                                range={false}\n                                onChange={(sel) => setMonthRange(sel.value)}\n                            />\n                        </div>\n                        <p className=\"text-xs text-gray-400\">{formatRange(monthRange)}</p>\n                    </div>\n                    <div className=\"space-y-2\">\n                        <label className=\"text-xs font-semibold text-gray-500 uppercase tracking-wide\">Year Mode</label>\n                        <div className=\"w-full max-w-80\">\n                            <DateRangePicker\n                                value={yearRange || undefined}\n                                placeholder=\"Select a year...\"\n                                selectionMode=\"year\"\n                                range={false}\n                                onChange={(sel) => setYearRange(sel.value)}\n                            />\n                        </div>\n                        <p className=\"text-xs text-gray-400\">{formatRange(yearRange)}</p>\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={selectionModeCode} title=\"Selection Modes\" />\n            </div>\n        </>\n    );\n};\n\nexport default SelectionModes;\n"
        },
        {
          "title": "SingleDatePicker",
          "code": "import React, { useState } from 'react';\nimport { DateRangePicker } from '../../../components';\nimport type { DateRangeValue } from '../../../components';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { CodeBlock } from '../../CodeBlock';\n\nconst singleDateCode = `<DateRangePicker\n  range={false}\n  placeholder=\"Pick a date...\"\n  onChange={(sel) => {\n    // sel.value is [Date, Date] where both are the same\n    const selectedDate = sel.value[0];\n    console.log(selectedDate);\n  }}\n/>`;\n\nconst SingleDatePicker: React.FC = () => {\n    const [value, setValue] = useState<DateRangeValue | null>(null);\n\n    return (\n        <>\n            <ComponentDemo title=\"Single Date Selection\" description=\"Set range={false} to select a single date instead of a range. The picker closes immediately on selection.\">\n                <div className=\"space-y-4\">\n                    <div className=\"w-full max-w-80\">\n                        <DateRangePicker\n                            value={value || undefined}\n                            range={false}\n                            placeholder=\"Pick a date...\"\n                            onChange={(sel) => setValue(sel.value)}\n                        />\n                    </div>\n                    {value && (\n                        <p className=\"text-xs text-gray-400\">\n                            Selected: {value[0].toLocaleDateString('en-US', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' })}\n                        </p>\n                    )}\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={singleDateCode} title=\"Single Date\" />\n            </div>\n        </>\n    );\n};\n\nexport default SingleDatePicker;\n"
        },
        {
          "title": "TodayButton",
          "code": "import React, { useState } from 'react';\nimport { DateRangePicker } from '../../../components';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst TodayButton: React.FC = () => {\n    const [presetRange, setPresetRange] = useState<[Date, Date]>([new Date(), new Date(Date.now() + 7 * 24 * 60 * 60 * 1000)]);\n\n    return (\n        <ComponentDemo title=\"With Today Button\" description=\"Date range picker with today button and custom label\">\n            <div className=\"w-full max-w-80\">\n                <DateRangePicker\n                    value={presetRange}\n                    showTodayButton={true}\n                    customLabel=\"Select Custom Range\"\n                    onChange={(selection) => setPresetRange(selection.value)}\n                    onClose={() => console.log('Picker closed')}\n                />\n            </div>\n        </ComponentDemo>\n    );\n};\n\nexport default TodayButton;\n"
        }
      ],
      "props": {
        "dateRangePickerProps": {
          "value": {
            "type": "DateRangeValue | string | number",
            "description": "Selected date range [Date, Date] or range option key"
          },
          "ranges": {
            "type": "RangeOption[]",
            "description": "Predefined quick range options"
          },
          "onChange": {
            "type": "(selection: DateSelectedCallbackArg) => void",
            "description": "Callback fired when date range selection changes"
          },
          "onClose": {
            "type": "() => void",
            "description": "Callback fired when date picker closes"
          },
          "dateFormat": {
            "type": "string",
            "default": "MM/dd/yyyy",
            "description": "Date format string for display"
          },
          "separator": {
            "type": "string",
            "default": "' ~ '",
            "description": "Separator between start and end dates"
          },
          "minDate": {
            "type": "Date",
            "description": "Minimum selectable date"
          },
          "maxDate": {
            "type": "Date",
            "description": "Maximum selectable date"
          },
          "customLabel": {
            "type": "string",
            "default": "Custom",
            "description": "Label for custom date range option"
          },
          "showTodayButton": {
            "type": "boolean",
            "default": false,
            "description": "Whether to show today button in date picker"
          },
          "disabled": {
            "type": "boolean",
            "default": false,
            "description": "Whether the picker is disabled"
          },
          "placeholder": {
            "type": "string",
            "description": "Placeholder text for empty state"
          },
          "position": {
            "type": "PopoverPosition",
            "default": "auto",
            "description": "Popover position: bottomStart, bottomEnd, topStart, topEnd, auto"
          },
          "id": {
            "type": "string",
            "description": "HTML id attribute"
          },
          "name": {
            "type": "string",
            "description": "Name attribute for form integration"
          },
          "className": {
            "type": "string",
            "description": "CSS class name for container"
          },
          "styles": {
            "type": "React.CSSProperties",
            "description": "Inline styles for container"
          },
          "classNames": {
            "type": "{ container?: string; control?: string; popover?: string }",
            "description": "Object with CSS classes for specific elements"
          },
          "range": {
            "type": "boolean",
            "default": "true",
            "description": "When false, picker selects a single date instead of a range. Closes immediately on selection."
          },
          "selectionMode": {
            "type": "'day' | 'week' | 'month' | 'year'",
            "default": "day",
            "description": "Controls what unit is selected: individual days, whole weeks, months, or years"
          },
          "firstDayOfWeek": {
            "type": "number",
            "default": "0",
            "description": "Day the week starts on (0=Sunday, 1=Monday, etc.). Affects calendar grid and week selection."
          },
          "args": {
            "type": "any",
            "description": "Additional arguments passed in onChange callback"
          },
          "locale": {
            "type": "any",
            "description": "Locale configuration for date formatting"
          }
        }
      },
      "storyDir": "date-range-picker"
    },
    "DiffViewer": {
      "name": "DiffViewer",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React from 'react';\nimport { DiffViewer } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { sampleNew, sampleOld } from './diff-sample';\n\nconst code = `import { DiffViewer } from 'fluxo-ui';\n\n<DiffViewer\n    oldValue={oldText}\n    newValue={newText}\n    oldTitle=\"before.js\"\n    newTitle=\"after.js\"\n/>`;\n\nconst BasicUsage: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Unified Diff\" description=\"Classic git-style unified diff with word-level highlights on changed lines.\">\n            <div style={{ width: '100%' }}>\n                <DiffViewer oldValue={sampleOld} newValue={sampleNew} oldTitle=\"before.js\" newTitle=\"after.js\" />\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default BasicUsage;\n"
        },
        {
          "title": "IgnoreOptions",
          "code": "import React, { useState } from 'react';\nimport { Checkbox, DiffViewer } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst oldText = `// Config file\nconst   HOST = \"localhost\";\nconst   PORT = 3000;\n\nconst   USER = \"Admin\";\nconst   PASS = \"Secret\";\n\n\nconst DB = \"mydb\";\nconst TIMEOUT = 30;\n`;\n\nconst newText = `// config file\nconst HOST = \"localhost\";\nconst PORT = 3000;\nconst user = \"admin\";\nconst pass = \"secret\";\nconst DB = \"mydb\";\nconst TIMEOUT = 30;\n`;\n\nconst code = `<DiffViewer\n    oldValue={oldText}\n    newValue={newText}\n    ignoreWhitespace\n    ignoreCase\n    ignoreEmptyLines\n/>`;\n\nconst IgnoreOptions: React.FC = () => {\n    const [ignoreWs, setIgnoreWs] = useState(false);\n    const [ignoreCase, setIgnoreCase] = useState(false);\n    const [ignoreEmpty, setIgnoreEmpty] = useState(false);\n\n    return (\n        <>\n            <ComponentDemo title=\"Ignore Options\" description=\"Toggle whitespace, case, and empty-line sensitivity.\">\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 14 }}>\n                    <div style={{ display: 'flex', gap: 16, flexWrap: 'wrap', padding: '10px 14px', background: 'var(--eui-bg-subtle)', border: '1px solid var(--eui-border-subtle)', borderRadius: 6 }}>\n                        <Checkbox checked={ignoreWs} onChange={(e) => setIgnoreWs(e.value)} label=\"Ignore whitespace\" />\n                        <Checkbox checked={ignoreCase} onChange={(e) => setIgnoreCase(e.value)} label=\"Ignore case\" />\n                        <Checkbox checked={ignoreEmpty} onChange={(e) => setIgnoreEmpty(e.value)} label=\"Ignore empty lines\" />\n                    </div>\n                    <DiffViewer\n                        oldValue={oldText}\n                        newValue={newText}\n                        ignoreWhitespace={ignoreWs}\n                        ignoreCase={ignoreCase}\n                        ignoreEmptyLines={ignoreEmpty}\n                    />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default IgnoreOptions;\n"
        },
        {
          "title": "LargeFile",
          "code": "import React, { useState } from 'react';\nimport { Button, DiffViewer, NumericInput } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { largeNew, largeOld } from './diff-sample';\n\nconst code = `<DiffViewer\n    oldValue={oldLarge}\n    newValue={newLarge}\n    variant=\"split\"\n    collapseUnchanged\n    maxLines={5000}\n    maxHeight={500}\n/>`;\n\nconst LargeFile: React.FC = () => {\n    const [show, setShow] = useState(false);\n    const [maxLines, setMaxLines] = useState<number>(2000);\n\n    return (\n        <>\n            <ComponentDemo title=\"Large File Performance\" description=\"Virtualized rendering. 2000+ lines diff smoothly. Use maxLines to cap comparison.\">\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 14 }}>\n                    <div style={{ display: 'flex', gap: 10, flexWrap: 'wrap', alignItems: 'center', padding: '10px 14px', background: 'var(--eui-bg-subtle)', border: '1px solid var(--eui-border-subtle)', borderRadius: 6 }}>\n                        <span style={{ fontSize: 13, color: 'var(--eui-text)' }}>maxLines:</span>\n                        <div style={{ width: 140 }}>\n                            <NumericInput value={maxLines} onChange={(e) => setMaxLines(Number(e.value) || 0)} />\n                        </div>\n                        <Button\n                            label={show ? 'Hide diff' : 'Render 2000-line diff'}\n                            size=\"sm\"\n                            variant=\"primary\"\n                            onClick={() => setShow((s) => !s)}\n                        />\n                    </div>\n                    {show && (\n                        <DiffViewer\n                            oldValue={largeOld}\n                            newValue={largeNew}\n                            variant=\"split\"\n                            collapseUnchanged\n                            maxLines={maxLines}\n                            maxHeight={480}\n                        />\n                    )}\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default LargeFile;\n"
        },
        {
          "title": "Variants",
          "code": "import React from 'react';\nimport { DiffViewer } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { sampleNew, sampleOld } from './diff-sample';\n\nconst code = `<DiffViewer variant=\"split\" oldValue={...} newValue={...} />\n<DiffViewer variant=\"inline\" oldValue={...} newValue={...} />\n<DiffViewer variant=\"minimal\" collapseUnchanged oldValue={...} newValue={...} />`;\n\nconst Variants: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Split View\" description=\"Side-by-side two-column layout.\">\n            <div style={{ width: '100%' }}>\n                <DiffViewer variant=\"split\" oldValue={sampleOld} newValue={sampleNew} oldTitle=\"before.js\" newTitle=\"after.js\" />\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n\n        <div className=\"mt-6\">\n            <ComponentDemo title=\"Inline Diff\" description=\"Compact inline word-level diff for small snippets.\">\n                <div style={{ width: '100%' }}>\n                    <DiffViewer variant=\"inline\" oldValue={sampleOld} newValue={sampleNew} />\n                </div>\n            </ComponentDemo>\n        </div>\n\n        <div className=\"mt-6\">\n            <ComponentDemo title=\"Collapse Unchanged\" description=\"Runs of unchanged lines are folded into context hunks.\">\n                <div style={{ width: '100%' }}>\n                    <DiffViewer oldValue={sampleOld} newValue={sampleNew} collapseUnchanged={2} />\n                </div>\n            </ComponentDemo>\n        </div>\n    </>\n);\n\nexport default Variants;\n"
        }
      ],
      "props": {
        "diffProps": {
          "oldValue": {
            "type": "string",
            "description": "The old/before text."
          },
          "newValue": {
            "type": "string",
            "description": "The new/after text."
          },
          "variant": {
            "type": "'unified' | 'split' | 'inline' | 'minimal'",
            "default": "'unified'",
            "description": "Diff display style."
          },
          "oldTitle": {
            "type": "string",
            "description": "Header label for the old side."
          },
          "newTitle": {
            "type": "string",
            "description": "Header label for the new side."
          },
          "showLineNumbers": {
            "type": "boolean",
            "default": "true",
            "description": "Show gutter line numbers."
          },
          "wordDiff": {
            "type": "boolean",
            "default": "true",
            "description": "Highlight word-level changes inside replaced lines."
          },
          "collapseUnchanged": {
            "type": "boolean | number",
            "default": "false",
            "description": "Fold unchanged runs. A number sets the context line count (default 3)."
          },
          "maxHeight": {
            "type": "number | string",
            "default": "480",
            "description": "Max scroll viewport height."
          },
          "ignoreWhitespace": {
            "type": "boolean",
            "default": "false",
            "description": "Collapse whitespace runs when comparing."
          },
          "ignoreCase": {
            "type": "boolean",
            "default": "false",
            "description": "Case-insensitive comparison."
          },
          "ignoreEmptyLines": {
            "type": "boolean",
            "default": "false",
            "description": "Treat blank lines as equal."
          },
          "maxLines": {
            "type": "number",
            "description": "Stop comparing after N lines. Larger files are truncated with a footer notice."
          },
          "rowHeight": {
            "type": "number",
            "default": "22",
            "description": "Row pixel height used for virtualization."
          },
          "highlight": {
            "type": "(line: string) => ReactNode",
            "description": "Custom syntax-highlight hook."
          }
        }
      },
      "storyDir": "diff-viewer"
    },
    "Dock": {
      "name": "Dock",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React, { useState } from 'react';\nimport {\n    DashboardIcon,\n    EditIcon,\n    FileUpload,\n    FolderIcon,\n    SearchIcon,\n    SettingsIcon,\n    ShareIcon,\n    TrashIcon,\n    UserIcon,\n} from '../../../assets/icons';\nimport { Dock } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { Dock } from 'fluxo-ui';\n\n<Dock\n  position=\"bottom\"\n  layout=\"pill\"\n  background=\"glass\"\n  mode=\"inline\"\n  items={[\n    { id: 'home', icon: DashboardIcon, label: 'Home' },\n    { id: 'docs', icon: FolderIcon, label: 'Docs' },\n    { id: 'edit', icon: EditIcon, label: 'Edit', badge: 3 },\n    { id: 'sep1', icon: ShareIcon, label: 'Share', separatorAfter: true },\n    { id: 'settings', icon: SettingsIcon, label: 'Settings' },\n  ]}\n/>`;\n\nconst BasicUsage: React.FC = () => {\n    const [last, setLast] = useState<string | null>(null);\n    return (\n        <>\n            <ComponentDemo\n                title=\"Default Dock\"\n                description=\"Hover an icon to see magnification and a tooltip. Set mode='fixed' (default) in real apps; this demo uses mode='inline' to live inside the example.\"\n            >\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16, alignItems: 'center' }}>\n                    <Dock\n                        position=\"bottom\"\n                        layout=\"pill\"\n                        background=\"glass\"\n                        mode=\"inline\"\n                        iconSize={44}\n                        magnification={1.5}\n                        magnificationDistance={70}\n                        onItemClick={(id) => setLast(id)}\n                        items={[\n                            { id: 'home', icon: DashboardIcon, label: 'Home' },\n                            { id: 'docs', icon: FolderIcon, label: 'Documents' },\n                            { id: 'upload', icon: FileUpload, label: 'Upload', badge: 2 },\n                            { id: 'edit', icon: EditIcon, label: 'Edit', separatorAfter: true },\n                            { id: 'share', icon: ShareIcon, label: 'Share' },\n                            { id: 'search', icon: SearchIcon, label: 'Search' },\n                            { id: 'profile', icon: UserIcon, label: 'Profile' },\n                            { id: 'sep2', icon: SettingsIcon, label: 'Settings', separatorAfter: true },\n                            { id: 'trash', icon: TrashIcon, label: 'Trash', disabled: true },\n                        ]}\n                    />\n                    <div\n                        style={{\n                            padding: '10px 14px',\n                            background: 'var(--eui-bg-subtle)',\n                            border: '1px solid var(--eui-border-subtle)',\n                            borderRadius: 6,\n                            fontSize: 13,\n                            textAlign: 'center',\n                            minWidth: 240,\n                        }}\n                    >\n                        Last activated: <strong>{last ?? '—'}</strong>\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "Layouts",
          "code": "import React from 'react';\nimport { DashboardIcon, FolderIcon, SettingsIcon, UserIcon } from '../../../assets/icons';\nimport { Dock, DockBackground, DockLayout } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst items = [\n    { id: '1', icon: DashboardIcon, label: 'Home' },\n    { id: '2', icon: FolderIcon, label: 'Files' },\n    { id: '3', icon: UserIcon, label: 'Profile' },\n    { id: '4', icon: SettingsIcon, label: 'Settings' },\n];\n\nconst layouts: DockLayout[] = ['pill', 'rectangle', 'floating', 'attached'];\nconst backgrounds: DockBackground[] = ['glass', 'solid', 'gradient', 'transparent'];\n\nconst code = `<Dock layout=\"pill\" background=\"glass\" mode=\"inline\" items={items} />\n<Dock layout=\"rectangle\" background=\"solid\" mode=\"inline\" items={items} />\n<Dock layout=\"floating\" background=\"gradient\" gradient={{ from: '#3b82f6', to: '#a855f7' }} mode=\"inline\" items={items} />\n<Dock layout=\"attached\" background=\"transparent\" mode=\"inline\" items={items} />`;\n\nconst Layouts: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Layouts × Backgrounds\" description=\"Cross product of every layout and background treatment.\">\n            <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 24, alignItems: 'center' }}>\n                {layouts.map((layout) => (\n                    <div key={layout} style={{ display: 'flex', flexDirection: 'column', gap: 8, alignItems: 'center' }}>\n                        <span style={{ fontSize: 12, color: 'var(--eui-text-muted)' }}>{layout}</span>\n                        <div style={{ display: 'flex', gap: 12, flexWrap: 'wrap', justifyContent: 'center' }}>\n                            {backgrounds.map((bg) => (\n                                <Dock\n                                    key={bg}\n                                    layout={layout}\n                                    background={bg}\n                                    gradient={bg === 'gradient' ? { from: '#3b82f6', to: '#a855f7' } : undefined}\n                                    mode=\"inline\"\n                                    iconSize={36}\n                                    magnification={1.3}\n                                    items={items}\n                                    ariaLabel={`${layout} dock with ${bg} background`}\n                                />\n                            ))}\n                        </div>\n                    </div>\n                ))}\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default Layouts;\n"
        },
        {
          "title": "Magnification",
          "code": "import React, { useState } from 'react';\nimport {\n    DashboardIcon,\n    FolderIcon,\n    SearchIcon,\n    SettingsIcon,\n    ShareIcon,\n    UserIcon,\n} from '../../../assets/icons';\nimport { Dock } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst items = [\n    { id: '1', icon: DashboardIcon, label: 'Home' },\n    { id: '2', icon: FolderIcon, label: 'Files' },\n    { id: '3', icon: SearchIcon, label: 'Search' },\n    { id: '4', icon: ShareIcon, label: 'Share' },\n    { id: '5', icon: UserIcon, label: 'Profile' },\n    { id: '6', icon: SettingsIcon, label: 'Settings' },\n];\n\nconst code = `<Dock magnification={1.6} magnificationDistance={80} items={items} />\n<Dock magnification={1} items={items} />`;\n\nconst Magnification: React.FC = () => {\n    const [magnification, setMagnification] = useState(1.6);\n    const [distance, setDistance] = useState(80);\n    const [iconSize, setIconSize] = useState(40);\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Magnification Controls\"\n                description=\"Tune the peak scale, falloff distance, and base icon size to match your app's feel. Set magnification to 1 to disable it.\"\n            >\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16, alignItems: 'center' }}>\n                    <Dock\n                        mode=\"inline\"\n                        layout=\"pill\"\n                        background=\"glass\"\n                        magnification={magnification}\n                        magnificationDistance={distance}\n                        iconSize={iconSize}\n                        items={items}\n                    />\n                    <div\n                        style={{\n                            display: 'grid',\n                            gridTemplateColumns: 'auto 1fr auto',\n                            gap: 12,\n                            alignItems: 'center',\n                            padding: '12px 16px',\n                            background: 'var(--eui-bg-subtle)',\n                            border: '1px solid var(--eui-border-subtle)',\n                            borderRadius: 6,\n                            width: '100%',\n                            maxWidth: 520,\n                            fontSize: 13,\n                        }}\n                    >\n                        <label htmlFor=\"magn\">Magnification</label>\n                        <input\n                            id=\"magn\"\n                            type=\"range\"\n                            min={1}\n                            max={3}\n                            step={0.05}\n                            value={magnification}\n                            onChange={(e) => setMagnification(Number(e.target.value))}\n                        />\n                        <span>{magnification.toFixed(2)}×</span>\n\n                        <label htmlFor=\"dist\">Distance</label>\n                        <input\n                            id=\"dist\"\n                            type=\"range\"\n                            min={20}\n                            max={200}\n                            step={4}\n                            value={distance}\n                            onChange={(e) => setDistance(Number(e.target.value))}\n                        />\n                        <span>{distance}px</span>\n\n                        <label htmlFor=\"icon\">Icon size</label>\n                        <input\n                            id=\"icon\"\n                            type=\"range\"\n                            min={28}\n                            max={72}\n                            step={2}\n                            value={iconSize}\n                            onChange={(e) => setIconSize(Number(e.target.value))}\n                        />\n                        <span>{iconSize}px</span>\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default Magnification;\n"
        },
        {
          "title": "Orientation",
          "code": "import React from 'react';\nimport {\n    DashboardIcon,\n    FolderIcon,\n    SettingsIcon,\n    ShareIcon,\n    UserIcon,\n} from '../../../assets/icons';\nimport { Dock } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst items = [\n    { id: '1', icon: DashboardIcon, label: 'Home' },\n    { id: '2', icon: FolderIcon, label: 'Files' },\n    { id: '3', icon: ShareIcon, label: 'Share' },\n    { id: '4', icon: UserIcon, label: 'Profile' },\n    { id: '5', icon: SettingsIcon, label: 'Settings' },\n];\n\nconst code = `<Dock position=\"bottom\" mode=\"inline\" items={items} />\n<Dock position=\"top\" mode=\"inline\" items={items} />\n<Dock position=\"left\" mode=\"inline\" items={items} />\n<Dock position=\"right\" mode=\"inline\" items={items} />`;\n\nconst Orientation: React.FC = () => (\n    <>\n        <ComponentDemo\n            title=\"Position & Orientation\"\n            description=\"Bottom and top render horizontally; left and right render vertically. Each side has its own anchor for tooltips.\"\n        >\n            <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: 24, width: '100%' }}>\n                {(['bottom', 'top', 'left', 'right'] as const).map((position) => (\n                    <div\n                        key={position}\n                        style={{\n                            border: '1px solid var(--eui-border-subtle)',\n                            borderRadius: 8,\n                            padding: 16,\n                            display: 'flex',\n                            flexDirection: 'column',\n                            alignItems: 'center',\n                            gap: 8,\n                        }}\n                    >\n                        <span style={{ fontSize: 12, color: 'var(--eui-text-muted)' }}>position=\"{position}\"</span>\n                        <Dock\n                            position={position}\n                            mode=\"inline\"\n                            layout=\"pill\"\n                            iconSize={36}\n                            magnification={1.3}\n                            items={items}\n                        />\n                    </div>\n                ))}\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default Orientation;\n"
        }
      ],
      "props": {
        "dockProps": {
          "items": {
            "type": "Array<DockItem>",
            "required": true,
            "description": "Dock items: { id, icon, label?, href?, onClick?, disabled?, badge?, separatorAfter? }"
          },
          "position": {
            "type": "'bottom' | 'top' | 'left' | 'right'",
            "default": "'bottom'",
            "description": "Edge of the viewport the dock attaches to"
          },
          "align": {
            "type": "'start' | 'center' | 'end'",
            "default": "'center'",
            "description": "Alignment along the dock axis"
          },
          "layout": {
            "type": "'pill' | 'rectangle' | 'floating' | 'attached'",
            "default": "'pill'",
            "description": "Visual treatment of the dock container"
          },
          "background": {
            "type": "'glass' | 'solid' | 'gradient' | 'transparent'",
            "default": "'glass'",
            "description": "Background treatment"
          },
          "gradient": {
            "type": "{ from: string; to: string; angle?: number }",
            "description": "Gradient stops, used when background is 'gradient'"
          },
          "magnification": {
            "type": "number",
            "default": "1.6",
            "description": "Peak scale factor of hovered/focused item; 1 disables magnification"
          },
          "magnificationDistance": {
            "type": "number",
            "default": "80",
            "description": "Radius (px) over which magnification falls off"
          },
          "iconSize": {
            "type": "number",
            "default": "40",
            "description": "Base icon container size in px"
          },
          "gap": {
            "type": "number",
            "default": "8",
            "description": "Base gap between dock items in px"
          },
          "autoHide": {
            "type": "boolean",
            "default": "false",
            "description": "Slide off-screen and reveal on edge hover/focus"
          },
          "autoHideDelay": {
            "type": "number",
            "default": "500",
            "description": "Milliseconds before hiding after pointer leaves"
          },
          "triggerZone": {
            "type": "number",
            "default": "12",
            "description": "Px-thick hot zone along the edge that reveals an auto-hidden dock"
          },
          "showTooltips": {
            "type": "boolean",
            "default": "true",
            "description": "Show item labels as tooltips on hover/focus"
          },
          "mode": {
            "type": "'fixed' | 'inline'",
            "default": "'fixed'",
            "description": "'fixed' attaches the dock to the viewport edge; 'inline' renders it inside its parent layout"
          },
          "onItemClick": {
            "type": "(id: string) => void",
            "description": "Fired when a dock item is activated"
          },
          "id": {
            "type": "string",
            "description": "HTML id attribute"
          },
          "className": {
            "type": "string",
            "description": "Additional CSS classes"
          },
          "ariaLabel": {
            "type": "string",
            "description": "Accessible label for the dock toolbar (default: 'Dock')"
          }
        }
      },
      "storyDir": "dock"
    },
    "DockedLayout": {
      "name": "DockedLayout",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React, { useState } from 'react';\nimport { DockedLayout } from '../../../components/docked-layout';\nimport type { PanelConfig } from '../../../components/docked-layout';\nimport { BarChartIcon, FilterIcon, FolderIcon, SearchIcon, SettingsIcon } from '../../../assets/icons';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst panels: PanelConfig[] = [\n    {\n        id: 'explorer',\n        title: 'Explorer',\n        icon: FolderIcon,\n        defaultPosition: 'left',\n        defaultState: 'pinned',\n        defaultSize: 220,\n        children: (\n            <div style={{ padding: '12px', color: 'var(--eui-text)' }}>\n                <div style={{ fontWeight: 600, fontSize: 12, marginBottom: 8, color: 'var(--eui-text-muted)' }}>FILES</div>\n                {['src/', 'public/', 'package.json', 'tsconfig.json', 'README.md'].map((f) => (\n                    <div\n                        key={f}\n                        style={{ padding: '4px 8px', borderRadius: 4, fontSize: 13, cursor: 'pointer' }}\n                        onMouseEnter={(e) => { (e.currentTarget as HTMLElement).style.background = 'var(--eui-bg-hover)'; }}\n                        onMouseLeave={(e) => { (e.currentTarget as HTMLElement).style.background = 'transparent'; }}\n                    >\n                        {f}\n                    </div>\n                ))}\n            </div>\n        ),\n    },\n    {\n        id: 'search',\n        title: 'Search',\n        icon: SearchIcon,\n        defaultPosition: 'left',\n        defaultState: 'pinned',\n        defaultSize: 220,\n        children: (\n            <div style={{ padding: '12px', color: 'var(--eui-text)' }}>\n                <input\n                    placeholder=\"Search files...\"\n                    style={{\n                        width: '100%', padding: '6px 10px', borderRadius: 4,\n                        border: '1px solid var(--eui-border)', background: 'var(--eui-bg-subtle)',\n                        color: 'var(--eui-text)', fontSize: 13, boxSizing: 'border-box',\n                    }}\n                    aria-label=\"Search files\"\n                />\n                <div style={{ marginTop: 12, fontSize: 12, color: 'var(--eui-text-muted)' }}>\n                    Type to search across files\n                </div>\n            </div>\n        ),\n    },\n    {\n        id: 'properties',\n        title: 'Properties',\n        icon: SettingsIcon,\n        defaultPosition: 'right',\n        defaultState: 'pinned',\n        defaultSize: 240,\n        children: (\n            <div style={{ padding: '12px', color: 'var(--eui-text)' }}>\n                <div style={{ fontWeight: 600, fontSize: 12, marginBottom: 8, color: 'var(--eui-text-muted)' }}>PROPERTIES</div>\n                {[['Name', 'MyComponent'], ['Type', 'React.FC'], ['Width', '100%'], ['Height', 'auto']].map(([k, v]) => (\n                    <div key={k} style={{ display: 'flex', justifyContent: 'space-between', padding: '4px 0', fontSize: 13, borderBottom: '1px solid var(--eui-border-subtle)' }}>\n                        <span style={{ color: 'var(--eui-text-muted)' }}>{k}</span>\n                        <span>{v}</span>\n                    </div>\n                ))}\n            </div>\n        ),\n    },\n    {\n        id: 'filters',\n        title: 'Filters',\n        icon: FilterIcon,\n        defaultPosition: 'right',\n        defaultState: 'auto-hide',\n        defaultSize: 240,\n        children: (\n            <div style={{ padding: '12px', color: 'var(--eui-text)' }}>\n                <div style={{ fontWeight: 600, fontSize: 12, marginBottom: 8, color: 'var(--eui-text-muted)' }}>FILTERS</div>\n                <div style={{ fontSize: 13, color: 'var(--eui-text-muted)' }}>No active filters</div>\n            </div>\n        ),\n    },\n    {\n        id: 'output',\n        title: 'Output',\n        icon: BarChartIcon,\n        defaultPosition: 'bottom',\n        defaultState: 'pinned',\n        defaultSize: 150,\n        children: (\n            <div style={{ padding: '8px 12px', fontFamily: 'Menlo, monospace', fontSize: 12, color: 'var(--eui-text)' }}>\n                <div style={{ color: '#22c55e' }}>[INFO] Build complete in 324ms</div>\n                <div style={{ color: 'var(--eui-text-muted)' }}>[INFO] Watching for file changes...</div>\n                <div style={{ color: '#f59e0b' }}>[WARN] Unused variable at line 42</div>\n            </div>\n        ),\n    },\n];\n\nconst code = `import { DockedLayout } from 'fluxo-ui';\nimport type { PanelConfig } from 'fluxo-ui';\n\nconst panels: PanelConfig[] = [\n  {\n    id: 'explorer',\n    title: 'Explorer',\n    icon: FolderIcon,\n    defaultPosition: 'left',\n    defaultState: 'pinned',\n    defaultSize: 220,\n    children: <ExplorerPanel />,\n  },\n  {\n    id: 'properties',\n    title: 'Properties',\n    icon: SettingsIcon,\n    defaultPosition: 'right',\n    defaultState: 'pinned',\n    defaultSize: 240,\n    children: <PropertiesPanel />,\n  },\n  {\n    id: 'output',\n    title: 'Output',\n    icon: BarChartIcon,\n    defaultPosition: 'bottom',\n    defaultState: 'pinned',\n    defaultSize: 150,\n    children: <OutputPanel />,\n  },\n];\n\n<DockedLayout panels={panels}>\n  <main style={{ padding: 24 }}>Main content here</main>\n</DockedLayout>`;\n\nconst BasicUsage: React.FC = () => {\n    const [count, setCount] = useState(0);\n\n    return (\n        <ComponentDemo\n            title=\"Basic Usage\"\n            description=\"Left, right, and bottom panels with tabbed groups. 'Filters' starts as auto-hide. Drag panel headers to re-dock. Click the pin button to toggle pinned/auto-hide.\"\n            centered={false}\n        >\n            <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16 }}>\n                <div style={{ height: 480, width: '100%', border: '1px solid var(--eui-border-subtle)', borderRadius: 6, overflow: 'hidden' }}>\n                    <DockedLayout panels={panels}>\n                        <div style={{ padding: 24, color: 'var(--eui-text)' }}>\n                            <h2 style={{ margin: '0 0 8px', fontSize: 20, fontWeight: 600 }}>Main Content</h2>\n                            <p style={{ color: 'var(--eui-text-muted)', fontSize: 14, margin: '0 0 16px' }}>\n                                Resize by dragging the edge between panel and center.\n                                Drag a panel header to re-dock it. Press the pin icon to toggle auto-hide.\n                            </p>\n                            <button\n                                onClick={() => setCount((c) => c + 1)}\n                                style={{\n                                    padding: '8px 16px', borderRadius: 6, border: '1px solid var(--eui-border)',\n                                    background: 'var(--eui-primary)', color: '#fff', cursor: 'pointer', fontSize: 13,\n                                }}\n                            >\n                                Clicked {count} times\n                            </button>\n                        </div>\n                    </DockedLayout>\n                </div>\n                <CodeBlock code={code} />\n            </div>\n        </ComponentDemo>\n    );\n};\n\n\nexport default BasicUsage;\n"
        },
        {
          "title": "FloatingPanels",
          "code": "import React from 'react';\nimport { DockedLayout } from '../../../components/docked-layout';\nimport type { PanelConfig } from '../../../components/docked-layout';\nimport { FolderIcon, PaletteIcon } from '../../../assets/icons';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst panels: PanelConfig[] = [\n    {\n        id: 'explorer3',\n        title: 'Explorer',\n        icon: FolderIcon,\n        defaultPosition: 'left',\n        defaultState: 'pinned',\n        defaultSize: 180,\n        children: <div style={{ padding: 12, color: 'var(--eui-text)', fontSize: 13 }}>Left panel content</div>,\n    },\n    {\n        id: 'color-picker3',\n        title: 'Color Picker',\n        icon: PaletteIcon,\n        defaultPosition: 'float',\n        defaultFloatPos: { x: 240, y: 60, width: 280, height: 200 },\n        children: (\n            <div style={{ padding: 12, color: 'var(--eui-text)', fontSize: 13 }}>\n                <div style={{ fontWeight: 600, fontSize: 12, marginBottom: 8, color: 'var(--eui-text-muted)' }}>COLOR SWATCHES</div>\n                <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>\n                    {['#ef4444', '#f97316', '#eab308', '#22c55e', '#3b82f6', '#8b5cf6', '#ec4899', '#14b8a6'].map((c) => (\n                        <div\n                            key={c}\n                            style={{ width: 28, height: 28, borderRadius: 4, background: c, cursor: 'pointer', border: '2px solid transparent' }}\n                            title={c}\n                        />\n                    ))}\n                </div>\n            </div>\n        ),\n    },\n];\n\nconst code = `const panels: PanelConfig[] = [\n  {\n    id: 'floating-panel',\n    title: 'Color Picker',\n    icon: PaletteIcon,\n    defaultPosition: 'float',\n    defaultFloatPos: { x: 240, y: 60, width: 280, height: 200 },\n    children: <ColorPickerContent />,\n  },\n];\n\n<DockedLayout panels={panels}>\n  <Content />\n</DockedLayout>`;\n\nexport const FloatingPanels: React.FC = () => (\n    <ComponentDemo\n        title=\"Floating Panels\"\n        description=\"Panels with defaultPosition='float' are freely draggable and resizable. Drag the header to move. Resize from the bottom-right corner. Use the dock buttons to attach to a side.\"\n        centered={false}\n    >\n        <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16 }}>\n            <div style={{ height: 360, border: '1px solid var(--eui-border-subtle)', borderRadius: 6, overflow: 'hidden', position: 'relative' }}>\n                <DockedLayout panels={panels}>\n                    <div style={{ padding: 24, color: 'var(--eui-text)' }}>\n                        <p style={{ margin: 0, fontSize: 14, color: 'var(--eui-text-muted)' }}>\n                            The \"Color Picker\" panel is floating. Drag its header to reposition it.\n                            Use the dock buttons in its header to attach it to a side.\n                        </p>\n                    </div>\n                </DockedLayout>\n            </div>\n            <CodeBlock code={code} />\n        </div>\n    </ComponentDemo>\n);\n"
        },
        {
          "title": "LayoutPersistence",
          "code": "import React, { useState } from 'react';\nimport { DockedLayout } from '../../../components/docked-layout';\nimport type { DockedLayoutState, PanelConfig } from '../../../components/docked-layout';\nimport { BarChartIcon, FolderIcon, SettingsIcon } from '../../../assets/icons';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst panels: PanelConfig[] = [\n    {\n        id: 'explorer4',\n        title: 'Explorer',\n        icon: FolderIcon,\n        defaultPosition: 'left',\n        defaultState: 'pinned',\n        defaultSize: 200,\n        children: <div style={{ padding: 12, color: 'var(--eui-text)', fontSize: 13 }}>Explorer content</div>,\n    },\n    {\n        id: 'properties4',\n        title: 'Properties',\n        icon: SettingsIcon,\n        defaultPosition: 'right',\n        defaultState: 'pinned',\n        defaultSize: 200,\n        children: <div style={{ padding: 12, color: 'var(--eui-text)', fontSize: 13 }}>Properties content</div>,\n    },\n    {\n        id: 'output4',\n        title: 'Output',\n        icon: BarChartIcon,\n        defaultPosition: 'bottom',\n        defaultState: 'pinned',\n        defaultSize: 120,\n        children: <div style={{ padding: 12, fontFamily: 'monospace', fontSize: 12, color: 'var(--eui-text)' }}>Build output…</div>,\n    },\n];\n\nconst code = `const [layoutState, setLayoutState] = useState<DockedLayoutState>();\n\n<DockedLayout\n  panels={panels}\n  layoutState={layoutState}\n  onChange={(state) => {\n    setLayoutState(state);\n    localStorage.setItem('layout', JSON.stringify(state));\n  }}\n>\n  <Content />\n</DockedLayout>`;\n\nexport const LayoutPersistence: React.FC = () => {\n    const [layoutState, setLayoutState] = useState<DockedLayoutState | undefined>(undefined);\n    const [saveCount, setSaveCount] = useState(0);\n\n    const handleChange = (state: DockedLayoutState) => {\n        setLayoutState(state);\n        setSaveCount((c) => c + 1);\n    };\n\n    return (\n        <ComponentDemo\n            title=\"Layout Persistence\"\n            description=\"The onChange callback fires on every layout change — resize, pin toggle, re-dock. Pass the state back via layoutState to restore it.\"\n            centered={false}\n        >\n            <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16 }}>\n                <div style={{ height: 360, border: '1px solid var(--eui-border-subtle)', borderRadius: 6, overflow: 'hidden' }}>\n                    <DockedLayout\n                        panels={panels}\n                        layoutState={layoutState}\n                        onChange={handleChange}\n                    >\n                        <div style={{ padding: 24, color: 'var(--eui-text)' }}>\n                            <p style={{ margin: 0, fontSize: 14, color: 'var(--eui-text-muted)' }}>\n                                Resize or re-dock panels. Layout changes are captured via onChange.\n                            </p>\n                        </div>\n                    </DockedLayout>\n                </div>\n                <div style={{ padding: '10px 14px', background: 'var(--eui-bg-subtle)', border: '1px solid var(--eui-border-subtle)', borderRadius: 6, fontSize: 13, color: 'var(--eui-text)' }}>\n                    Layout onChange fired: <strong>{saveCount}</strong> times\n                </div>\n                <CodeBlock code={code} />\n            </div>\n        </ComponentDemo>\n    );\n};\n"
        },
        {
          "title": "TabModes",
          "code": "import React, { useState } from 'react';\nimport { DockedLayout } from '../../../components/docked-layout';\nimport type { PanelConfig, TabMode } from '../../../components/docked-layout';\nimport { FolderIcon, SearchIcon, SettingsIcon } from '../../../assets/icons';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst panels: PanelConfig[] = [\n    {\n        id: 'explorer2',\n        title: 'Explorer',\n        icon: FolderIcon,\n        defaultPosition: 'left',\n        defaultState: 'pinned',\n        defaultSize: 180,\n        children: (\n            <div style={{ padding: 12, color: 'var(--eui-text)', fontSize: 13 }}>\n                <div style={{ color: 'var(--eui-text-muted)', fontSize: 11, fontWeight: 600, marginBottom: 8 }}>FILES</div>\n                {['index.ts', 'App.tsx', 'styles.css'].map((f) => (\n                    <div key={f} style={{ padding: '3px 6px', cursor: 'pointer', borderRadius: 3 }}>{f}</div>\n                ))}\n            </div>\n        ),\n    },\n    {\n        id: 'search2',\n        title: 'Search',\n        icon: SearchIcon,\n        defaultPosition: 'left',\n        defaultState: 'pinned',\n        defaultSize: 180,\n        children: (\n            <div style={{ padding: 12, color: 'var(--eui-text)', fontSize: 13 }}>\n                <input\n                    placeholder=\"Search...\"\n                    aria-label=\"Search\"\n                    style={{ width: '100%', padding: '5px 8px', borderRadius: 4, border: '1px solid var(--eui-border)', background: 'var(--eui-bg-subtle)', color: 'var(--eui-text)', fontSize: 12, boxSizing: 'border-box' }}\n                />\n            </div>\n        ),\n    },\n    {\n        id: 'settings2',\n        title: 'Settings',\n        icon: SettingsIcon,\n        defaultPosition: 'left',\n        defaultState: 'pinned',\n        defaultSize: 180,\n        children: (\n            <div style={{ padding: 12, color: 'var(--eui-text)', fontSize: 13 }}>\n                <div style={{ color: 'var(--eui-text-muted)', fontSize: 11, fontWeight: 600, marginBottom: 8 }}>SETTINGS</div>\n                <div>Theme: Blue</div>\n            </div>\n        ),\n    },\n];\n\nconst code = (mode: TabMode) => `<DockedLayout panels={panels} tabMode=\"${mode}\">\n  <Content />\n</DockedLayout>`;\n\nexport const TabModes: React.FC = () => {\n    const [mode, setMode] = useState<TabMode>('icon');\n\n    return (\n        <ComponentDemo\n            title=\"Tab Modes\"\n            description=\"Switch between 'icon' (compact icon-only) and 'icon-label' (icon with label text below) activity bar modes.\"\n            centered={false}\n        >\n            <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16 }}>\n                <div style={{ display: 'flex', gap: 8 }}>\n                    {(['icon', 'icon-label'] as TabMode[]).map((m) => (\n                        <button\n                            key={m}\n                            onClick={() => setMode(m)}\n                            style={{\n                                padding: '6px 14px', borderRadius: 6, border: '1px solid var(--eui-border)',\n                                background: mode === m ? 'var(--eui-primary)' : 'var(--eui-bg-subtle)',\n                                color: mode === m ? '#fff' : 'var(--eui-text)', cursor: 'pointer', fontSize: 13,\n                            }}\n                        >\n                            {m}\n                        </button>\n                    ))}\n                </div>\n                <div style={{ height: 360, border: '1px solid var(--eui-border-subtle)', borderRadius: 6, overflow: 'hidden' }}>\n                    <DockedLayout panels={panels} tabMode={mode}>\n                        <div style={{ padding: 24, color: 'var(--eui-text)' }}>\n                            <strong>tabMode: \"{mode}\"</strong>\n                            <p style={{ color: 'var(--eui-text-muted)', fontSize: 14, marginTop: 8 }}>\n                                Activity bar shows {mode === 'icon' ? 'icons only' : 'icons with labels'}.\n                            </p>\n                        </div>\n                    </DockedLayout>\n                </div>\n                <CodeBlock code={code(mode)} />\n            </div>\n        </ComponentDemo>\n    );\n};\n"
        }
      ],
      "props": {
        "dockedLayoutProps": {
          "panels": {
            "type": "PanelConfig[]",
            "required": true,
            "description": "Array of panel configuration objects."
          },
          "children": {
            "type": "React.ReactNode",
            "description": "The main center content area."
          },
          "layoutState": {
            "type": "DockedLayoutState",
            "description": "Controlled layout state. Use onChange to keep in sync."
          },
          "onChange": {
            "type": "(state: DockedLayoutState) => void",
            "description": "Fired on every layout change for persistence."
          },
          "tabMode": {
            "type": "'icon' | 'icon-label'",
            "default": "'icon'",
            "description": "Activity bar display mode."
          },
          "className": {
            "type": "string",
            "description": "Additional CSS class names."
          },
          "style": {
            "type": "React.CSSProperties",
            "description": "Inline styles for the outer container."
          }
        },
        "panelConfigProps": {
          "id": {
            "type": "string",
            "required": true,
            "description": "Unique panel identifier."
          },
          "title": {
            "type": "string",
            "required": true,
            "description": "Panel display title and activity bar tooltip."
          },
          "icon": {
            "type": "SVGIcon",
            "required": true,
            "description": "Icon rendered in the activity bar. Must be from icons.ts."
          },
          "children": {
            "type": "React.ReactNode",
            "description": "Panel body content."
          },
          "defaultPosition": {
            "type": "'left' | 'right' | 'bottom' | 'float'",
            "default": "'left'",
            "description": "Initial dock position."
          },
          "defaultState": {
            "type": "'pinned' | 'auto-hide'",
            "default": "'pinned'",
            "description": "Initial pin state."
          },
          "defaultSize": {
            "type": "number",
            "default": "260",
            "description": "Initial size in pixels."
          },
          "minSize": {
            "type": "number",
            "default": "100",
            "description": "Minimum size in pixels during resize."
          },
          "defaultVisible": {
            "type": "boolean",
            "default": "true",
            "description": "Whether visible in activity bar on initial render."
          },
          "defaultFloatPos": {
            "type": "FloatPos",
            "description": "Initial position/size for floating: { x, y, width, height }."
          },
          "userCanMove": {
            "type": "boolean",
            "default": "true",
            "description": "Whether end user can re-dock the panel."
          },
          "userCanResize": {
            "type": "boolean",
            "default": "true",
            "description": "Whether end user can resize the panel."
          },
          "userCanClose": {
            "type": "boolean",
            "default": "true",
            "description": "Whether end user can close the panel."
          },
          "userCanTogglePin": {
            "type": "boolean",
            "default": "true",
            "description": "Whether end user can toggle pin/auto-hide."
          }
        }
      },
      "storyDir": "docked-layout"
    },
    "DragDrop": {
      "name": "DragDrop",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicDragDrop",
          "code": "import React, { useState } from 'react';\nimport { Draggable, Droppable } from '../../../components/drag-drop';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { sourceItems } from './drag-drop-story-data';\n\nconst code = `import { Draggable, Droppable } from 'fluxo-ui';\n\nfunction DragDropExample() {\n  const [items] = useState(['Item 1', 'Item 2', 'Item 3']);\n  const [droppedItems, setDroppedItems] = useState([]);\n\n  const handleDrop = (source, target) => {\n    setDroppedItems([...droppedItems, source.item]);\n  };\n\n  return (\n    <div className=\"flex gap-8\">\n      {/* Source */}\n      <div>\n        {items.map((item, index) => (\n          <Draggable\n            key={index}\n            containerId=\"source\"\n            index={index}\n            item={item}\n            itemType=\"task\"\n          >\n            <div className=\"bg-blue-600 px-4 py-3 rounded cursor-move\">\n              {item}\n            </div>\n          </Draggable>\n        ))}\n      </div>\n\n      {/* Drop Zone — built-in highlight indicator, no manual border logic needed */}\n      <Droppable\n        containerId=\"target\"\n        index={0}\n        accept=\"task\"\n        onDrop={handleDrop}\n        className=\"min-h-50 border-2 border-dashed border-gray-300 rounded-lg p-4\"\n      >\n        {droppedItems.length > 0\n          ? droppedItems.map((item, idx) => <div key={idx}>{item}</div>)\n          : 'Drop here'}\n      </Droppable>\n    </div>\n  );\n}`;\n\nconst BasicDragDrop: React.FC = () => {\n    const [droppedItems, setDroppedItems] = useState<string[]>([]);\n\n    const handleDrop = (source: any) => {\n        setDroppedItems((prev) => [...prev, source.item]);\n    };\n\n    return (\n        <>\n            <ComponentDemo title=\"Simple Drag & Drop\">\n                <div className=\"flex flex-col sm:flex-row gap-6 sm:gap-8\">\n                    <div className=\"flex-1\">\n                        <h3 className=\"text-sm font-medium mb-3\" style={{ color: 'var(--eui-text)' }}>\n                            Draggable Items\n                        </h3>\n                        <div className=\"space-y-2\">\n                            {sourceItems.map((item, index) => (\n                                <Draggable key={index} containerId=\"source\" index={index} item={item} itemType=\"task\">\n                                    <div className=\"bg-blue-600 text-white px-4 py-3 rounded cursor-move hover:bg-blue-500 transition-colors\">\n                                        {item}\n                                    </div>\n                                </Draggable>\n                            ))}\n                        </div>\n                    </div>\n                    <div className=\"flex-1\">\n                        <h3 className=\"text-sm font-medium mb-3\" style={{ color: 'var(--eui-text)' }}>Drop Zone</h3>\n                        <Droppable\n                            containerId=\"target\"\n                            index={0}\n                            accept=\"task\"\n                            onDrop={handleDrop}\n                            className=\"min-h-50 rounded-lg border-2 border-dashed p-4\"\n                            style={{ borderColor: 'var(--eui-border)', background: 'var(--eui-bg-subtle)' }}\n                        >\n                            {droppedItems.length > 0 ? (\n                                <div className=\"space-y-2\">\n                                    {droppedItems.map((item, idx) => (\n                                        <div key={idx} className=\"bg-green-600 text-white px-4 py-3 rounded\">\n                                            {item}\n                                        </div>\n                                    ))}\n                                </div>\n                            ) : (\n                                <div className=\"text-center py-16\" style={{ color: 'var(--eui-text-muted)' }}>Drop items here</div>\n                            )}\n                        </Droppable>\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default BasicDragDrop;\n"
        },
        {
          "title": "DragHandleStrict",
          "code": "import React, { useRef, useState } from 'react';\nimport { Draggable } from '../../../components/drag-drop';\nimport { Sortable } from '../../../components/drag-drop';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\ninterface Card {\n    id: number;\n    title: string;\n    description: string;\n}\n\nconst INITIAL: Card[] = [\n    { id: 1, title: 'Install grip handles', description: 'Only the grip on the left starts a drag.' },\n    { id: 2, title: 'Body is interactive', description: 'You can still click buttons and select text in the body.' },\n    { id: 3, title: 'Touch friendly', description: 'Works the same on mouse, touch, and pen.' },\n];\n\nconst code = `function HandleRow({ card }) {\n  const handleRef = useRef(null);\n  return (\n    <Draggable\n      containerId=\"handles\"\n      index={card.index}\n      item={card}\n      dragHandle={handleRef}\n    >\n      <div className=\"row\">\n        <button ref={handleRef} aria-label=\"Drag\">≡</button>\n        <div className=\"body\">{card.title}</div>\n      </div>\n    </Draggable>\n  );\n}`;\n\nconst HandleRow: React.FC<{ card: Card; index: number }> = ({ card, index }) => {\n    const handleRef = useRef<HTMLButtonElement | null>(null);\n    return (\n        <Draggable containerId=\"handle-strict\" index={index} id={card.id} item={card} itemType=\"card\" dragHandle={handleRef}>\n            <div className=\"flex items-stretch gap-3 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg overflow-hidden\">\n                <button\n                    ref={handleRef}\n                    type=\"button\"\n                    className=\"px-3 flex items-center text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 cursor-grab active:cursor-grabbing bg-gray-50 dark:bg-gray-900\"\n                    aria-label=\"Drag handle\"\n                >\n                    <svg width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"currentColor\">\n                        <circle cx=\"5\" cy=\"3\" r=\"1.2\" /><circle cx=\"11\" cy=\"3\" r=\"1.2\" />\n                        <circle cx=\"5\" cy=\"8\" r=\"1.2\" /><circle cx=\"11\" cy=\"8\" r=\"1.2\" />\n                        <circle cx=\"5\" cy=\"13\" r=\"1.2\" /><circle cx=\"11\" cy=\"13\" r=\"1.2\" />\n                    </svg>\n                </button>\n                <div className=\"py-3 pr-4 flex-1 min-w-0\">\n                    <div className=\"font-semibold text-gray-900 dark:text-gray-100 text-sm\">{card.title}</div>\n                    <div className=\"text-xs text-gray-500 dark:text-gray-400 mt-0.5\">{card.description}</div>\n                    <button\n                        type=\"button\"\n                        className=\"mt-2 text-xs text-indigo-600 dark:text-indigo-400 hover:underline\"\n                        onClick={(e) => { e.stopPropagation(); alert('Body button still works!'); }}\n                    >\n                        Click a body button\n                    </button>\n                </div>\n            </div>\n        </Draggable>\n    );\n};\n\nconst DragHandleStrict: React.FC = () => {\n    const [cards, setCards] = useState<Card[]>(INITIAL);\n\n    return (\n        <>\n            <ComponentDemo title=\"Strict Drag Handles (handle-only activation)\">\n                <div className=\"w-full max-w-lg\">\n                    <Sortable items={cards} onChange={setCards} idProp=\"id\" itemType=\"card\" gap=\"0.5rem\">\n                        {(card, idx) => <HandleRow card={card} index={idx} />}\n                    </Sortable>\n                </div>\n                <p className=\"mt-3 text-xs text-gray-500 dark:text-gray-500 text-center max-w-lg\">\n                    Try dragging the card body — nothing happens. Drag from the grip icon on the left to reorder. The body remains fully\n                    interactive (text selection, button clicks).\n                </p>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default DragHandleStrict;\n"
        },
        {
          "title": "DropPositionAuto",
          "code": "import React, { useState } from 'react';\nimport { Draggable, Droppable } from '../../../components/drag-drop';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\ninterface Row {\n    id: number;\n    label: string;\n}\n\nconst INITIAL: Row[] = [\n    { id: 1, label: 'Alpha' },\n    { id: 2, label: 'Bravo' },\n    { id: 3, label: 'Charlie' },\n    { id: 4, label: 'Delta' },\n    { id: 5, label: 'Echo' },\n];\n\nconst code = `// dropPosition=\"auto\" splits each target in half and returns\n// the exact insert index via position ('before' | 'after').\n<Droppable\n  containerId=\"list\"\n  index={i}\n  dropPosition=\"auto\"\n  dropIndicator=\"line\"\n  edgeThreshold={12}\n  onDrop={(source, target) => {\n    // target.index already reflects before/after choice\n    setItems((prev) => reorder(prev, source.index, target.index));\n  }}\n>\n  {item}\n</Droppable>`;\n\nfunction reorder(items: Row[], from: number, to: number): Row[] {\n    const next = [...items];\n    const [moved] = next.splice(from, 1);\n    let insertAt = to;\n    if (from < to) insertAt -= 1;\n    next.splice(insertAt, 0, moved!);\n    return next;\n}\n\nconst DropPositionAuto: React.FC = () => {\n    const [items, setItems] = useState<Row[]>(INITIAL);\n\n    return (\n        <>\n            <ComponentDemo title=\"Drop Position Auto (before / after insertion)\">\n                <div className=\"flex flex-col gap-1 w-full max-w-md\">\n                    {items.map((row, i) => (\n                        <Droppable\n                            key={row.id}\n                            containerId=\"drop-pos-auto\"\n                            index={i}\n                            id={row.id}\n                            accept=\"row\"\n                            dropIndicator=\"line\"\n                            dropPosition=\"auto\"\n                            edgeThreshold={12}\n                            onDrop={(source, target) => {\n                                if (source.containerId !== 'drop-pos-auto') return;\n                                if (source.index === target.index || source.index + 1 === target.index) return;\n                                setItems((prev) => reorder(prev, source.index, target.index));\n                            }}\n                        >\n                            <Draggable containerId=\"drop-pos-auto\" index={i} id={row.id} item={row} itemType=\"row\">\n                                <div className=\"bg-indigo-600 text-white px-4 py-3 rounded-md shadow-sm cursor-grab select-none\">\n                                    {row.label}\n                                </div>\n                            </Draggable>\n                        </Droppable>\n                    ))}\n                </div>\n                <p className=\"mt-3 text-xs text-gray-500 dark:text-gray-500 text-center max-w-md\">\n                    Hover the top half of any row to see the insertion line on the top edge; hover the bottom half to see it on the\n                    bottom edge. Dropping lands exactly where the line is shown.\n                </p>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default DropPositionAuto;\n"
        },
        {
          "title": "FileDropZone",
          "code": "import React, { useState } from 'react';\nimport { Droppable } from '../../../components/drag-drop';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\ninterface DroppedFile {\n    name: string;\n    size: number;\n    type: string;\n}\n\nconst code = `<Droppable\n  containerId=\"files\"\n  index={0}\n  acceptFiles\n  onDrop={(source) => {\n    const fileList = source.item.files as FileList;\n    // handle files...\n  }}\n>\n  <div>Drop files from your desktop here</div>\n</Droppable>`;\n\nfunction formatSize(bytes: number): string {\n    if (bytes < 1024) return `${bytes} B`;\n    if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n    return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;\n}\n\nconst FileDropZone: React.FC = () => {\n    const [files, setFiles] = useState<DroppedFile[]>([]);\n\n    return (\n        <>\n            <ComponentDemo title=\"Native OS File Drop\">\n                <div className=\"w-full max-w-xl\">\n                    <Droppable\n                        containerId=\"file-drop-zone\"\n                        index={0}\n                        acceptFiles\n                        dropIndicator=\"highlight\"\n                        className=\"min-h-40 flex items-center justify-center p-6 border-2 border-dashed border-gray-300 dark:border-gray-600 rounded-lg bg-gray-50 dark:bg-gray-900/30\"\n                        onDrop={(source) => {\n                            const fileList = (source.item as { files?: FileList }).files;\n                            if (!fileList) return;\n                            const next: DroppedFile[] = [];\n                            for (let i = 0; i < fileList.length; i++) {\n                                const f = fileList[i]!;\n                                next.push({ name: f.name, size: f.size, type: f.type || 'unknown' });\n                            }\n                            setFiles((prev) => [...next, ...prev].slice(0, 20));\n                        }}\n                    >\n                        <div className=\"text-center\">\n                            <div className=\"text-3xl mb-1\">📁</div>\n                            <div className=\"text-sm font-medium text-gray-700 dark:text-gray-200\">Drop files from your desktop here</div>\n                            <div className=\"text-xs text-gray-500 dark:text-gray-500 mt-0.5\">Accepts any file type — uses native OS drag</div>\n                        </div>\n                    </Droppable>\n                    {files.length > 0 && (\n                        <div className=\"mt-4 space-y-1\">\n                            <div className=\"text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wide\">\n                                Recently dropped ({files.length})\n                            </div>\n                            {files.map((f, i) => (\n                                <div\n                                    key={`${f.name}-${i}`}\n                                    className=\"flex items-center justify-between text-sm bg-white dark:bg-gray-800 rounded border border-gray-200 dark:border-gray-700 px-3 py-1.5\"\n                                >\n                                    <span className=\"truncate text-gray-900 dark:text-gray-100\">{f.name}</span>\n                                    <span className=\"text-xs text-gray-500 dark:text-gray-400 ml-3 flex-shrink-0\">\n                                        {formatSize(f.size)} · {f.type}\n                                    </span>\n                                </div>\n                            ))}\n                        </div>\n                    )}\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default FileDropZone;\n"
        },
        {
          "title": "MultiContainer",
          "code": "import cn from 'classnames';\nimport React, { useState } from 'react';\nimport { Draggable, Droppable } from '../../../components/drag-drop';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\n\nconst code = `import { Draggable, Droppable } from 'fluxo-ui';\n\nfunction KanbanBoard() {\n  const [items, setItems] = useState({\n    todo: ['Task A', 'Task B', 'Task C'],\n    done: [],\n  });\n\n  const handleDrop = (source, target) => {\n    const sourceContainer = source.containerId;\n    const targetContainer = target.containerId;\n\n    if (sourceContainer === targetContainer) return;\n\n    setItems(prev => ({\n      todo: sourceContainer === 'todo'\n        ? prev.todo.filter((_, i) => i !== source.index)\n        : prev.todo,\n      done: targetContainer === 'done'\n        ? [...prev.done, source.item]\n        : prev.done,\n    }));\n  };\n\n  return (\n    <div className=\"flex flex-col sm:flex-row gap-6 sm:gap-8\">\n      <Droppable containerId=\"todo\" index={0} accept=\"task\" onDrop={handleDrop}>\n        {({ dropRef, isOver }) => (\n          <div ref={dropRef}>\n            {items.todo.map((item, index) => (\n              <Draggable\n                key={index}\n                containerId=\"todo\"\n                index={index}\n                item={item}\n                itemType=\"task\"\n              >\n                <div>{item}</div>\n              </Draggable>\n            ))}\n          </div>\n        )}\n      </Droppable>\n\n      <Droppable containerId=\"done\" index={0} accept=\"task\" onDrop={handleDrop}>\n        {({ dropRef }) => (\n          <div ref={dropRef}>\n            {items.done.map((item, idx) => (\n              <div key={idx}>{item}</div>\n            ))}\n          </div>\n        )}\n      </Droppable>\n    </div>\n  );\n}`;\n\nconst MultiContainer: React.FC = () => {\n    const { isDark } = useStoryTheme();\n    const [multiContainerItems, setMultiContainerItems] = useState({\n        source: ['Task A', 'Task B', 'Task C'],\n        done: [] as string[],\n    });\n\n    const handleMultiContainerDrop = (source: any, target: any) => {\n        const sourceContainer = source.containerId;\n        const targetContainer = target.containerId;\n\n        if (sourceContainer === targetContainer) {\n            return;\n        }\n\n        setMultiContainerItems((prev) => ({\n            source: sourceContainer === 'source' ? prev.source.filter((_: string, i: number) => i !== source.index) : prev.source,\n            done: targetContainer === 'done' ? [...prev.done, source.item] : prev.done,\n        }));\n    };\n\n    return (\n        <>\n            <ComponentDemo title=\"Kanban-style Board\">\n                <div className=\"flex flex-col sm:flex-row gap-6 sm:gap-8\">\n                    <div className=\"flex-1\">\n                        <h3 className={cn('text-sm font-medium mb-3', { 'text-gray-300': isDark, 'text-gray-700': !isDark })}>To Do</h3>\n                        <Droppable\n                            containerId=\"source\"\n                            index={0}\n                            accept=\"task\"\n                            onDrop={handleMultiContainerDrop}\n                            className=\"border-2 border-dashed border-gray-300 dark:border-gray-600 rounded-lg p-4 min-h-62.5 bg-gray-50 dark:bg-gray-900/40\"\n                        >\n                            <div className=\"space-y-2\">\n                                {multiContainerItems.source.map((item, index) => (\n                                    <Draggable key={index} containerId=\"source\" index={index} item={item} itemType=\"task\">\n                                        <div className=\"bg-gray-200 dark:bg-gray-700 text-gray-800 dark:text-white px-4 py-3 rounded hover:bg-gray-300 dark:hover:bg-gray-600 transition-colors\">\n                                            {item}\n                                        </div>\n                                    </Draggable>\n                                ))}\n                            </div>\n                        </Droppable>\n                    </div>\n                    <div className=\"flex-1\">\n                        <h3 className={cn('text-sm font-medium mb-3', { 'text-gray-300': isDark, 'text-gray-700': !isDark })}>Done</h3>\n                        <Droppable\n                            containerId=\"done\"\n                            index={0}\n                            accept=\"task\"\n                            onDrop={handleMultiContainerDrop}\n                            className=\"border-2 border-dashed border-gray-300 dark:border-gray-600 rounded-lg p-4 min-h-62.5 bg-gray-50 dark:bg-gray-900/40\"\n                        >\n                            <div className=\"space-y-2\">\n                                {multiContainerItems.done.map((item, index) => (\n                                    <div key={index} className=\"bg-green-600 text-white px-4 py-3 rounded\">\n                                        {item}\n                                    </div>\n                                ))}\n                                {multiContainerItems.done.length === 0 && (\n                                    <div className=\"text-gray-500 text-center py-8\">Drop completed tasks here</div>\n                                )}\n                            </div>\n                        </Droppable>\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default MultiContainer;\n"
        },
        {
          "title": "RenderProps",
          "code": "import cn from 'classnames';\nimport React, { useState } from 'react';\nimport { Draggable, Droppable } from '../../../components/drag-drop';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\n\nconst code = `<Draggable containerId=\"source\" index={0} item={item} itemType=\"feature\">\n  {({ isDragging, dragRef }) => (\n    <div\n      ref={dragRef}\n      className={\\`\\${isDragging ? 'opacity-50 scale-105' : ''}\\`}\n    >\n      {item}\n    </div>\n  )}\n</Draggable>\n\n<Droppable containerId=\"target\" index={0} accept=\"feature\" onDrop={handleDrop}>\n  {({ dropRef, isOver, canDrop }) => (\n    <div\n      ref={dropRef}\n      className={\\`\\${isOver && canDrop ? 'bg-green-500/20' : ''}\\`}\n    >\n      {isOver ? 'Release to drop' : 'Drop here'}\n    </div>\n  )}\n</Droppable>`;\n\nconst RenderProps: React.FC = () => {\n    const { isDark } = useStoryTheme();\n    const [customStyleItems, setCustomStyleItems] = useState({\n        available: ['Feature 1', 'Feature 2', 'Feature 3'],\n        selected: [] as string[],\n    });\n\n    const handleCustomStyleDrop = (source: any, target: any) => {\n        const sourceContainer = source.containerId;\n        const targetContainer = target.containerId;\n\n        if (sourceContainer === targetContainer) {\n            return;\n        }\n\n        setCustomStyleItems((prev) => ({\n            available: sourceContainer === 'available'\n                ? prev.available.filter((_: string, i: number) => i !== source.index)\n                : prev.available,\n            selected: targetContainer === 'selected'\n                ? [...prev.selected, source.item]\n                : prev.selected,\n        }));\n    };\n\n    return (\n        <>\n            <ComponentDemo title=\"Visual Feedback with Render Props\">\n                <div className=\"flex flex-col sm:flex-row gap-6 sm:gap-8\">\n                    <div className=\"flex-1\">\n                        <h3 className={cn('text-sm font-medium mb-3', { 'text-gray-300': isDark, 'text-gray-700': !isDark })}>Available Features</h3>\n                        <div className=\"space-y-2\">\n                            {customStyleItems.available.map((item, index) => (\n                                <Draggable\n                                    key={index}\n                                    containerId=\"available\"\n                                    index={index}\n                                    item={item}\n                                    itemType=\"feature\"\n                                >\n                                    {({ isDragging, dragRef }) => (\n                                        <div\n                                            ref={dragRef}\n                                            className={`px-4 py-3 rounded cursor-move transition-all ${\n                                                isDragging\n                                                    ? 'bg-blue-400 opacity-50 scale-105'\n                                                    : 'bg-blue-600 hover:bg-blue-500'\n                                            } text-white`}\n                                        >\n                                            {item}\n                                        </div>\n                                    )}\n                                </Draggable>\n                            ))}\n                        </div>\n                    </div>\n                    <div className=\"flex-1\">\n                        <h3 className={cn('text-sm font-medium mb-3', { 'text-gray-300': isDark, 'text-gray-700': !isDark })}>Selected Features</h3>\n                        <Droppable\n                            containerId=\"selected\"\n                            index={0}\n                            accept=\"feature\"\n                            onDrop={handleCustomStyleDrop}\n                        >\n                            {({ dropRef, isOver, canDrop }) => (\n                                <div\n                                    ref={dropRef}\n                                    className={`border-2 border-dashed rounded p-4 min-h-50 transition-all ${\n                                        isOver && canDrop\n                                            ? 'border-purple-500 bg-purple-500/20 scale-105'\n                                            : canDrop\n                                            ? 'border-purple-500 dark:border-purple-600 bg-purple-50 dark:bg-purple-500/5'\n                                            : 'border-gray-300 dark:border-gray-700'\n                                    }`}\n                                >\n                                    {customStyleItems.selected.length > 0 ? (\n                                        <div className=\"space-y-2\">\n                                            {customStyleItems.selected.map((item, idx) => (\n                                                <div\n                                                    key={idx}\n                                                    className=\"bg-purple-600 text-white px-4 py-3 rounded\"\n                                                >\n                                                    {item}\n                                                </div>\n                                            ))}\n                                        </div>\n                                    ) : (\n                                        <div className=\"text-gray-500 text-center py-16\">\n                                            {isOver ? 'Release to drop' : 'Drag features here'}\n                                        </div>\n                                    )}\n                                </div>\n                            )}\n                        </Droppable>\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default RenderProps;\n"
        },
        {
          "title": "SetupSection",
          "code": "import cn from 'classnames';\nimport React from 'react';\nimport { CodeBlock } from '../../CodeBlock';\nimport { useStoryTheme } from '../../StoryThemeContext';\n\nconst SetupSection: React.FC = () => {\n    const { isDark } = useStoryTheme();\n\n    return (\n        <>\n            <p className={cn('mb-4', { 'text-gray-400': isDark, 'text-gray-600': !isDark })}>\n                Drag & drop components work out of the box — no provider wrapping, no extra peer dependencies.\n                Just import from <code className=\"px-1.5 py-0.5 rounded bg-gray-200 dark:bg-gray-700 text-sm\">fluxo-ui</code> and go.\n            </p>\n            <CodeBlock\n                title=\"Use it directly\"\n                code={`import { Draggable, Droppable } from 'fluxo-ui';\n\nfunction MyList() {\n  return (\n    <>\n      <Draggable containerId=\"list\" index={0} item={myItem}>\n        <div>Drag me</div>\n      </Draggable>\n      <Droppable containerId=\"target\" index={0} onDrop={handleDrop}>\n        <div>Drop here</div>\n      </Droppable>\n    </>\n  );\n}`}\n            />\n            <p className={cn('mt-4 text-sm', { 'text-gray-400': isDark, 'text-gray-600': !isDark })}>\n                The built-in engine supports mouse, touch, pen, drag handles, delay activation, custom live previews, auto-scroll\n                near container edges, and scroll-aware positioning — all with zero third-party dependencies. An optional{' '}\n                <code className=\"px-1.5 py-0.5 rounded bg-gray-200 dark:bg-gray-700 text-sm\">DragDropProvider</code>{' '}\n                is still exported for backwards compatibility but is no longer required.\n            </p>\n        </>\n    );\n};\n\nexport default SetupSection;\n"
        }
      ],
      "props": {
        "draggableProps": {
          "containerId": {
            "type": "string",
            "required": true,
            "description": "Unique identifier for the container this draggable belongs to"
          },
          "index": {
            "type": "number",
            "required": true,
            "description": "Index of the item in the container"
          },
          "item": {
            "type": "any",
            "required": true,
            "description": "The actual item data being dragged"
          },
          "id": {
            "type": "string | number",
            "description": "Optional unique identifier for the item"
          },
          "itemType": {
            "type": "string",
            "default": "'any'",
            "description": "Type of the draggable item (used for drop validation)"
          },
          "args": {
            "type": "any",
            "description": "Additional arguments to pass along with drag data"
          },
          "canDrag": {
            "type": "boolean",
            "default": "true",
            "description": "Whether the item can be dragged"
          },
          "onRemove": {
            "type": "(source: { index: number; id?: string | number }, dropResult: DropResult | null) => void",
            "description": "Callback when item is removed from its original container"
          },
          "onDragStart": {
            "type": "(item: DragItem, monitor: DragSourceMonitor) => void",
            "description": "Callback when drag starts"
          },
          "onDragEnd": {
            "type": "(item: DragItem | undefined, monitor: DragSourceMonitor) => void",
            "description": "Callback when drag ends"
          },
          "className": {
            "type": "string",
            "description": "Additional CSS classes"
          },
          "draggingClassName": {
            "type": "string",
            "description": "Extra CSS classes applied only while the item is being dragged"
          },
          "hideDefaultPreview": {
            "type": "boolean",
            "default": "false",
            "description": "Hide the default browser drag preview (useful for custom overlays)"
          },
          "children": {
            "type": "ReactNode | ((props: DraggableRenderProps) => ReactNode)",
            "description": "Children can be ReactNode or render prop function"
          }
        },
        "droppableProps": {
          "containerId": {
            "type": "string",
            "required": true,
            "description": "Unique identifier for the container"
          },
          "index": {
            "type": "number",
            "required": true,
            "description": "Index position within the container"
          },
          "id": {
            "type": "string | number",
            "description": "Optional unique identifier"
          },
          "accept": {
            "type": "string | string[]",
            "default": "'any'",
            "description": "Type(s) of draggable items this droppable accepts"
          },
          "args": {
            "type": "any",
            "description": "Additional arguments to pass to drop handler"
          },
          "canDrop": {
            "type": "boolean | ((item: DragItem, monitor: DropTargetMonitor) => boolean)",
            "default": "true",
            "description": "Whether dropping is currently allowed"
          },
          "onDrop": {
            "type": "(source: DragItem, target: DropResult) => void",
            "description": "Callback when an item is dropped"
          },
          "onHover": {
            "type": "(item: DragItem, monitor: DropTargetMonitor) => void",
            "description": "Callback when a draggable item hovers over this droppable"
          },
          "className": {
            "type": "string",
            "description": "Additional CSS classes"
          },
          "dropIndicator": {
            "type": "'highlight' | 'line' | 'none'",
            "default": "'highlight'",
            "description": "Built-in visual indicator style for drop targets"
          },
          "linePosition": {
            "type": "'start' | 'end'",
            "default": "'start'",
            "description": "Where to render the insertion line when dropIndicator='line'"
          },
          "orientation": {
            "type": "'vertical' | 'horizontal'",
            "default": "'vertical'",
            "description": "Direction of the line indicator"
          },
          "children": {
            "type": "ReactNode | ((props: DroppableRenderProps) => ReactNode)",
            "description": "Children can be ReactNode or render prop function"
          }
        }
      },
      "storyDir": "drag-drop"
    },
    "Sortable": {
      "name": "Sortable",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicSortable",
          "code": "import React, { useState } from 'react';\nimport { Sortable } from '../../../components/drag-drop';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { Sortable } from 'fluxo-ui';\n\nfunction SortableList() {\n  const [items, setItems] = useState([\n    'First Item',\n    'Second Item',\n    'Third Item',\n    'Fourth Item',\n  ]);\n\n  return (\n    <Sortable\n      items={items}\n      onChange={(newItems) => setItems(newItems)}\n      dropIndicator=\"line\"\n    >\n      {(item, index) => (\n        <div className=\"bg-blue-600 px-4 py-3 rounded-md\">\n          {index + 1}. {item}\n        </div>\n      )}\n    </Sortable>\n  );\n}`;\n\nconst BasicSortable: React.FC = () => {\n    const [basicItems, setBasicItems] = useState(['First Item', 'Second Item', 'Third Item', 'Fourth Item', 'Fifth Item']);\n\n    return (\n        <>\n            <ComponentDemo title=\"Simple List Reordering\">\n                <Sortable items={basicItems} onChange={(newItems) => setBasicItems(newItems)}>\n                    {(item, index) => (\n                        <div className=\"bg-blue-600 text-white px-4 py-3 rounded-md shadow-sm hover:bg-blue-500 transition-colors\">\n                            {index + 1}. {item}\n                        </div>\n                    )}\n                </Sortable>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default BasicSortable;\n"
        },
        {
          "title": "ComplexItems",
          "code": "import React, { useState } from 'react';\nimport { Sortable } from '../../../components/drag-drop';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport type { Task } from './sortable-story-data';\nimport { getPriorityColor } from './sortable-story-data';\n\nconst initialTasks: Task[] = [\n    { id: 1, title: 'Setup project', description: 'Initialize repository and install dependencies', priority: 'high' },\n    { id: 2, title: 'Design UI mockups', description: 'Create wireframes and mockups', priority: 'medium' },\n    { id: 3, title: 'Implement features', description: 'Build core functionality', priority: 'high' },\n    { id: 4, title: 'Write tests', description: 'Add unit and integration tests', priority: 'medium' },\n    { id: 5, title: 'Deploy to production', description: 'Configure CI/CD and deploy', priority: 'low' },\n];\n\nconst code = `import { Sortable } from 'fluxo-ui';\n\ninterface Task {\n  id: number;\n  title: string;\n  description?: string;\n  priority?: 'low' | 'medium' | 'high';\n}\n\nfunction TaskList() {\n  const [tasks, setTasks] = useState<Task[]>([\n    { id: 1, title: 'Setup project', priority: 'high' },\n    { id: 2, title: 'Design UI', priority: 'medium' },\n    { id: 3, title: 'Deploy', priority: 'low' },\n  ]);\n\n  return (\n    <Sortable\n      items={tasks}\n      onChange={(newTasks) => setTasks(newTasks)}\n      className=\"space-y-3\"\n    >\n      {(task) => (\n        <div className=\"bg-gray-100 rounded-lg p-4 cursor-move\">\n          <h3>{task.title}</h3>\n          <span className={\\`priority-\\${task.priority}\\`}>\n            {task.priority}\n          </span>\n        </div>\n      )}\n    </Sortable>\n  );\n}`;\n\nconst ComplexItems: React.FC = () => {\n    const [taskList, setTaskList] = useState<Task[]>(initialTasks);\n\n    return (\n        <>\n            <ComponentDemo title=\"Task List with Priority\">\n                <Sortable items={taskList} onChange={(newItems) => setTaskList(newItems)} gap=\"0.75rem\">\n                    {(task, index) => (\n                        <div className=\"bg-white dark:bg-gray-800 rounded-lg p-4 shadow-sm hover:shadow-md transition-shadow border border-gray-200 dark:border-gray-700\">\n                            <div className=\"flex items-start gap-3\">\n                                <div className=\"shrink-0 mt-1\">\n                                    <div className={`w-3 h-3 rounded-full ${getPriorityColor(task.priority)}`} />\n                                </div>\n                                <div className=\"flex-1\">\n                                    <h3 className=\"text-gray-900 dark:text-white font-medium mb-1\">{task.title}</h3>\n                                    {task.description && <p className=\"text-gray-600 dark:text-gray-400 text-sm\">{task.description}</p>}\n                                </div>\n                                <div className=\"shrink-0\">\n                                    <span className=\"text-gray-500 text-sm\">#{index + 1}</span>\n                                </div>\n                            </div>\n                        </div>\n                    )}\n                </Sortable>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default ComplexItems;\n"
        },
        {
          "title": "DragHandles",
          "code": "import React, { useState } from 'react';\nimport { Sortable } from '../../../components/drag-drop';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { Sortable } from 'fluxo-ui';\n\nfunction ListWithHandles() {\n  const [items, setItems] = useState(['Item 1', 'Item 2', 'Item 3']);\n\n  return (\n    <Sortable\n      items={items}\n      onChange={setItems}\n      provideDragRef\n    >\n      {(item, index, { draggable }) => (\n        <div className=\"flex items-center gap-3\">\n          {/* Custom drag handle */}\n          <div ref={draggable?.dragRef} className=\"cursor-move\">\n            ⋮⋮\n          </div>\n          <div className=\"flex-1\">{item}</div>\n        </div>\n      )}\n    </Sortable>\n  );\n}`;\n\nconst DragHandles: React.FC = () => {\n    const [items, setItems] = useState(['First Item', 'Second Item', 'Third Item']);\n\n    return (\n        <>\n            <ComponentDemo title=\"Using provideDragRef for Custom Handles\">\n                <Sortable items={items} onChange={(newItems) => setItems(newItems)} provideDragRef>\n                    {(item, index, { draggable }) => (\n                        <div className=\"bg-white dark:bg-gray-800 rounded-lg p-4 flex items-center gap-3 border border-gray-200 dark:border-gray-700 shadow-sm\">\n                            <div\n                                ref={draggable?.dragRef}\n                                className=\"cursor-grab active:cursor-grabbing text-gray-400 dark:text-gray-500 hover:text-gray-700 dark:hover:text-white transition-colors\"\n                            >\n                                <svg className=\"w-5 h-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n                                    <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M4 8h16M4 16h16\" />\n                                </svg>\n                            </div>\n                            <div className=\"flex-1 text-gray-900 dark:text-white\">{item}</div>\n                            <div className=\"text-gray-500 text-sm\">#{index + 1}</div>\n                        </div>\n                    )}\n                </Sortable>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default DragHandles;\n"
        },
        {
          "title": "MultipleLists",
          "code": "import cn from 'classnames';\nimport React, { useState } from 'react';\nimport { Sortable } from '../../../components/drag-drop';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\nimport type { KanbanItem } from './sortable-story-data';\nimport { columnColors, columnTitles, getTypeIcon } from './sortable-story-data';\n\nconst initialColumns: Record<string, KanbanItem[]> = {\n    todo: [\n        { id: 101, text: 'Review pull requests', type: 'review' },\n        { id: 102, text: 'Update documentation', type: 'docs' },\n        { id: 103, text: 'Fix bug in login', type: 'bug' },\n    ],\n    inProgress: [{ id: 104, text: 'Implement dark mode', type: 'feature' }],\n    done: [{ id: 105, text: 'Setup CI/CD pipeline', type: 'devops' }],\n};\n\nconst code = `import { Sortable } from 'fluxo-ui';\n\nfunction KanbanBoard() {\n  const [columns, setColumns] = useState({\n    todo: [{ id: 1, text: 'Task 1' }],\n    inProgress: [{ id: 2, text: 'Task 2' }],\n    done: [{ id: 3, text: 'Task 3' }],\n  });\n\n  const handleDrop = (columnKey, source, target) => {\n    if (source.containerId !== target.containerId) {\n      const sourceKey = Object.keys(columns).find(\n        key => columns[key].some(item => item.id === source.item.id)\n      );\n\n      setColumns({\n        ...columns,\n        [sourceKey]: columns[sourceKey].filter(\n          item => item.id !== source.item.id\n        ),\n        [columnKey]: [...columns[columnKey], source.item],\n      });\n    }\n  };\n\n  return (\n    <div className=\"grid grid-cols-1 md:grid-cols-3 gap-4\">\n      {Object.keys(columns).map(columnKey => (\n        <Sortable\n          key={columnKey}\n          items={columns[columnKey]}\n          onChange={(newItems) =>\n            setColumns({ ...columns, [columnKey]: newItems })\n          }\n          onDrop={(source, target) =>\n            handleDrop(columnKey, source, target)\n          }\n          showPlaceholder\n        >\n          {(item) => <div>{item.text}</div>}\n        </Sortable>\n      ))}\n    </div>\n  );\n}`;\n\nconst MultipleLists: React.FC = () => {\n    const { isDark } = useStoryTheme();\n    const [columns, setColumns] = useState<Record<string, KanbanItem[]>>(initialColumns);\n\n    return (\n        <>\n            <ComponentDemo title=\"Kanban Board with Sortable Columns\">\n                <div className=\"grid grid-cols-1 md:grid-cols-3 gap-4\">\n                    {(Object.keys(columns) as Array<keyof typeof columns>).map((columnKey) => (\n                        <div key={columnKey}>\n                            <h3 className={cn('text-sm font-medium mb-3', { 'text-gray-300': isDark, 'text-gray-700': !isDark })}>\n                                {columnTitles[columnKey]}\n                            </h3>\n                            <Sortable\n                                items={columns[columnKey]}\n                                onChange={(newItems) => {\n                                    setColumns((prev) => ({ ...prev, [columnKey]: newItems }));\n                                }}\n                                onDrop={(source) => {\n                                    setColumns((prev) => {\n                                        const newState = { ...prev };\n                                        (Object.keys(newState) as Array<keyof typeof columns>).forEach((key) => {\n                                            newState[key] = newState[key].filter((item: KanbanItem) => item.id !== source.item.id);\n                                        });\n                                        newState[columnKey] = [...newState[columnKey], source.item];\n                                        return newState;\n                                    });\n                                }}\n                                className=\"min-h-75 bg-gray-50 dark:bg-gray-900/50 rounded-lg p-3\"\n                                dropIndicator=\"highlight\"\n                                showPlaceholder\n                                placeholder={<div className=\"text-center text-gray-500 text-sm\">Drop here</div>}\n                            >\n                                {(item) => (\n                                    <div className={`rounded-lg p-3 transition-colors border ${columnColors[columnKey]}`}>\n                                        <div className=\"flex items-center gap-2\">\n                                            <span className=\"text-lg\">{getTypeIcon(item.type)}</span>\n                                            <span className=\"text-gray-800 dark:text-white text-sm flex-1\">{item.text}</span>\n                                        </div>\n                                    </div>\n                                )}\n                            </Sortable>\n                        </div>\n                    ))}\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default MultipleLists;\n"
        },
        {
          "title": "ScrollableLongList",
          "code": "import React, { useState, useMemo } from 'react';\nimport { Sortable } from '../../../components/drag-drop';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\ninterface ListRow {\n    id: number;\n    label: string;\n    color: string;\n}\n\nconst PALETTE = ['#2563eb', '#16a34a', '#d97706', '#dc2626', '#7c3aed', '#0891b2', '#db2777', '#65a30d'];\n\nfunction makeRows(count: number, offset = 0): ListRow[] {\n    return Array.from({ length: count }, (_, i) => ({\n        id: i + offset + 1,\n        label: `Row #${i + offset + 1}`,\n        color: PALETTE[(i + offset) % PALETTE.length]!,\n    }));\n}\n\nconst code = `// Scroll-aware Sortable: 500 items inside a 320px-tall scrollable container.\n// Positioning is computed from viewport coordinates + getBoundingClientRect,\n// so it remains correct at any scroll position. Auto-scroll engages near edges.\nconst [items, setItems] = useState(() => makeRows(500));\n\n<div style={{ height: 320, overflow: 'auto' }}>\n  <Sortable items={items} onChange={setItems} idProp=\"id\">\n    {(row) => <div style={{ background: row.color }}>{row.label}</div>}\n  </Sortable>\n</div>`;\n\nconst ScrollableLongList: React.FC = () => {\n    const [items, setItems] = useState<ListRow[]>(() => makeRows(500));\n\n    const stats = useMemo(() => ({ count: items.length, first: items[0]?.label, last: items[items.length - 1]?.label }), [items]);\n\n    return (\n        <>\n            <ComponentDemo title=\"Scrollable Container + Long List (500 items)\">\n                <div className=\"mb-3 text-sm text-gray-600 dark:text-gray-400\">\n                    {stats.count.toLocaleString()} rows · first: <strong>{stats.first}</strong> · last: <strong>{stats.last}</strong>\n                </div>\n                <div\n                    style={{ height: 320, overflow: 'auto' }}\n                    className=\"rounded-lg border border-gray-300 dark:border-gray-700 bg-gray-50 dark:bg-gray-900/40 p-3\"\n                >\n                    <Sortable items={items} onChange={setItems} idProp=\"id\" gap=\"0.375rem\">\n                        {(row) => (\n                            <div\n                                className=\"rounded-md px-3 py-2 text-white text-sm font-medium select-none\"\n                                style={{ background: row.color }}\n                            >\n                                {row.label}\n                            </div>\n                        )}\n                    </Sortable>\n                </div>\n                <p className=\"mt-3 text-xs text-gray-500 dark:text-gray-500\">\n                    Drag a row near the top or bottom edge of the container — it auto-scrolls. Scroll the container while holding a drag, or\n                    scroll the page — the insertion line stays locked to where the item will actually land.\n                </p>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default ScrollableLongList;\n"
        },
        {
          "title": "SetupSection",
          "code": "import cn from 'classnames';\nimport React from 'react';\nimport { CodeBlock } from '../../CodeBlock';\nimport { useStoryTheme } from '../../StoryThemeContext';\n\nconst SetupSection: React.FC = () => {\n    const { isDark } = useStoryTheme();\n\n    return (\n        <>\n            <p className={cn('mb-4', { 'text-gray-400': isDark, 'text-gray-600': !isDark })}>\n                <code className=\"px-1.5 py-0.5 rounded bg-gray-200 dark:bg-gray-700 text-sm\">Sortable</code>{' '}\n                is available from the main <code className=\"px-1.5 py-0.5 rounded bg-gray-200 dark:bg-gray-700 text-sm\">fluxo-ui</code>{' '}\n                entry — no provider wrapping and no extra peer dependencies.\n            </p>\n            <CodeBlock\n                title=\"Use it directly\"\n                code={`import { Sortable } from 'fluxo-ui';\n\nfunction MyList() {\n  const [items, setItems] = useState(['One', 'Two', 'Three']);\n  return (\n    <Sortable items={items} onChange={setItems}>\n      {(item) => <div className=\"row\">{item}</div>}\n    </Sortable>\n  );\n}`}\n            />\n            <p className={cn('mt-4 text-sm', { 'text-gray-400': isDark, 'text-gray-600': !isDark })}>\n                Sortable ships with scroll-aware positioning, auto-scroll near container edges, touch and pen support, optional\n                drag handles, delay activation, and fine-grained{' '}\n                <code className=\"px-1.5 py-0.5 rounded bg-gray-200 dark:bg-gray-700 text-sm\">canDragItem</code> /{' '}\n                <code className=\"px-1.5 py-0.5 rounded bg-gray-200 dark:bg-gray-700 text-sm\">canDropItem</code> callbacks — all in the main library bundle.\n            </p>\n        </>\n    );\n};\n\nexport default SetupSection;\n"
        }
      ],
      "props": {
        "sortableProps": {
          "items": {
            "type": "T[]",
            "required": true,
            "description": "Array of items to render"
          },
          "accept": {
            "type": "string | string[]",
            "description": "Type(s) of external draggable items this sortable accepts"
          },
          "itemType": {
            "type": "string",
            "default": "'any'",
            "description": "Default item type for items within this sortable"
          },
          "itemTypeProp": {
            "type": "string",
            "description": "Property name on items to get their type (for mixed item types)"
          },
          "args": {
            "type": "any",
            "description": "Additional arguments passed to callbacks"
          },
          "allowRemove": {
            "type": "boolean",
            "default": "false",
            "description": "Auto-remove items from source list on cross-container drop (default false — manage removal in destination onDrop)"
          },
          "showPlaceholder": {
            "type": "boolean",
            "default": "false",
            "description": "Whether to show a placeholder drop zone at the end"
          },
          "placeholder": {
            "type": "ReactNode",
            "description": "Custom placeholder content"
          },
          "dropIndicator": {
            "type": "'highlight' | 'line' | 'none'",
            "default": "'line'",
            "description": "Drop indicator style — 'line' shows an insertion line between items, 'highlight' glows the slot"
          },
          "orientation": {
            "type": "'vertical' | 'horizontal'",
            "default": "'vertical'",
            "description": "Layout direction for items"
          },
          "gap": {
            "type": "string",
            "default": "'0.5rem'",
            "description": "Gap between items (any valid CSS length)"
          },
          "as": {
            "type": "ElementType",
            "default": "'div'",
            "description": "HTML tag name for the container element"
          },
          "provideDropRef": {
            "type": "boolean",
            "default": "false",
            "description": "Pass drop ref to children render function"
          },
          "provideDragRef": {
            "type": "boolean",
            "default": "false",
            "description": "Pass drag ref to children render function"
          },
          "keyboardReorder": {
            "type": "boolean",
            "default": "true",
            "description": "Enable keyboard reorder: Space/Enter to grab, arrow keys to move, Enter to drop, Escape to cancel. Adds role=listbox and aria-grabbed semantics."
          },
          "itemAriaLabel": {
            "type": "(item: T, index: number) => string",
            "description": "Compute the accessible name announced for each draggable slot. Defaults to 'Item N of M'."
          },
          "onChange": {
            "type": "(items: T[], args?: any, event?: SortableChangeEvent) => void",
            "required": true,
            "description": "Callback when items are reordered or changed"
          },
          "onDrop": {
            "type": "(source: DragItem, target: DropResult, args?: any) => void",
            "description": "Callback when an external item is dropped"
          },
          "onRemove": {
            "type": "(removed: { index: number; id?: string | number }, dropResult: DropResult | null) => void",
            "description": "Callback when an item is removed (dragged out)"
          },
          "className": {
            "type": "string",
            "description": "Additional CSS classes"
          },
          "children": {
            "type": "(item: T, index: number, refs: { draggable?: DraggableRenderProps; droppable?: DroppableRenderProps }) => ReactNode",
            "required": true,
            "description": "Render function for each item"
          }
        }
      },
      "storyDir": "sortable"
    },
    "Drawer": {
      "name": "Drawer",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React, { useState } from 'react';\nimport { Button, Drawer } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { Drawer, Button } from 'fluxo-ui';\n\nconst [open, setOpen] = useState(false);\n\n<Button onClick={() => setOpen(true)}>Open Drawer</Button>\n\n<Drawer\n  open={open}\n  onClose={() => setOpen(false)}\n  header=\"Drawer Title\"\n>\n  <p>Drawer body content goes here.</p>\n</Drawer>`;\n\nconst BasicUsage: React.FC = () => {\n    const [open, setOpen] = useState(false);\n\n    return (\n        <>\n            <ComponentDemo title=\"Default Drawer\" description=\"A right-side drawer with header and close button.\">\n                <Button onClick={() => setOpen(true)}>Open Drawer</Button>\n            </ComponentDemo>\n            <Drawer open={open} onClose={() => setOpen(false)} header=\"Drawer Title\">\n                <div className=\"space-y-4\">\n                    <p>This is the drawer body content. You can place any content here including forms, lists, or details panels.</p>\n                    <p>Click the X button, press Escape, or click the backdrop to close.</p>\n                </div>\n            </Drawer>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "BottomSheet",
          "code": "import React, { useState } from 'react';\nimport { Button, Drawer } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { Drawer } from 'fluxo-ui';\n\nconst [open, setOpen] = useState(false);\n\n<Drawer\n    open={open}\n    onClose={() => setOpen(false)}\n    position=\"bottom\"\n    variant=\"sheet\"\n    snapPoints={[0.3, 0.6, 0.9]}\n    initialSnap={1}\n    title=\"Select an option\"\n>\n    {/* sheet body */}\n</Drawer>`;\n\nconst BottomSheet: React.FC = () => {\n    const [openSnap, setOpenSnap] = useState(false);\n    const [openDismiss, setOpenDismiss] = useState(false);\n    const [openCustom, setOpenCustom] = useState(false);\n    const [snapIdx, setSnapIdx] = useState(1);\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Snap points\"\n                description=\"A bottom sheet with three snap points (30%, 60%, 90% of viewport). Drag the handle up or down — the sheet settles on the nearest snap.\"\n            >\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16 }}>\n                    <div>\n                        <Button label=\"Open snap sheet\" onClick={() => setOpenSnap(true)} />\n                    </div>\n                    <div\n                        style={{\n                            padding: '10px 14px',\n                            background: 'var(--eui-bg-subtle)',\n                            border: '1px solid var(--eui-border-subtle)',\n                            borderRadius: 6,\n                            fontSize: 12,\n                            color: 'var(--eui-text-muted)',\n                        }}\n                    >\n                        Last settled snap index: <strong style={{ color: 'var(--eui-text)' }}>{snapIdx}</strong>\n                    </div>\n                </div>\n                <Drawer\n                    open={openSnap}\n                    onClose={() => setOpenSnap(false)}\n                    position=\"bottom\"\n                    variant=\"sheet\"\n                    snapPoints={[0.3, 0.6, 0.9]}\n                    initialSnap={1}\n                    onSnapChange={setSnapIdx}\n                    title=\"Pick a destination\"\n                >\n                    <p style={{ marginTop: 0, color: 'var(--eui-text-muted)' }}>\n                        Drag the handle at the top to resize the sheet. Drag below the smallest snap (or fast-swipe down) to dismiss.\n                    </p>\n                    {Array.from({ length: 20 }).map((_, i) => (\n                        <div\n                            key={i}\n                            style={{\n                                padding: '10px 12px',\n                                borderBottom: '1px solid var(--eui-border-subtle)',\n                                color: 'var(--eui-text)',\n                            }}\n                        >\n                            Option {i + 1}\n                        </div>\n                    ))}\n                </Drawer>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n\n            <ComponentDemo\n                title=\"Drag-to-dismiss\"\n                description=\"Sheet without snap points — drag down past 40% of its height or fast-swipe down to dismiss.\"\n                className=\"mt-4\"\n            >\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 12 }}>\n                    <div>\n                        <Button label=\"Open simple sheet\" variant=\"secondary\" onClick={() => setOpenDismiss(true)} />\n                    </div>\n                </div>\n                <Drawer\n                    open={openDismiss}\n                    onClose={() => setOpenDismiss(false)}\n                    position=\"bottom\"\n                    variant=\"sheet\"\n                    size=\"55vh\"\n                    title=\"Quick info\"\n                >\n                    <p style={{ color: 'var(--eui-text)' }}>This sheet has a fixed height. Try dragging the handle down to dismiss.</p>\n                </Drawer>\n            </ComponentDemo>\n\n            <ComponentDemo\n                title=\"Top sheet\"\n                description=\"Sheets aren't limited to the bottom — the same drag/snap behavior works with position='top'.\"\n                className=\"mt-4\"\n            >\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 12 }}>\n                    <div>\n                        <Button label=\"Open top sheet\" variant=\"secondary\" onClick={() => setOpenCustom(true)} />\n                    </div>\n                </div>\n                <Drawer\n                    open={openCustom}\n                    onClose={() => setOpenCustom(false)}\n                    position=\"top\"\n                    variant=\"sheet\"\n                    snapPoints={['25vh', '50vh']}\n                    initialSnap={0}\n                    title=\"Notifications\"\n                >\n                    <ul style={{ paddingLeft: 18, color: 'var(--eui-text)' }}>\n                        <li>Pull-down to expand</li>\n                        <li>Quick toggles</li>\n                        <li>Recent activity</li>\n                    </ul>\n                </Drawer>\n            </ComponentDemo>\n        </>\n    );\n};\n\nexport default BottomSheet;\n"
        },
        {
          "title": "CustomContent",
          "code": "import React, { useState } from 'react';\nimport { Button, Drawer, TextInput } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { Drawer, Button, TextInput } from 'fluxo-ui';\n\n<Drawer\n  open={open}\n  onClose={() => setOpen(false)}\n  header=\"Edit Profile\"\n  footer={\n    <div className=\"flex gap-2 justify-end\">\n      <Button variant=\"default\" onClick={() => setOpen(false)}>Cancel</Button>\n      <Button variant=\"primary\" onClick={handleSave}>Save</Button>\n    </div>\n  }\n  size=\"480px\"\n>\n  <form className=\"space-y-4\">\n    <TextInput label=\"Full Name\" value={name} onChange={setName} />\n    <TextInput label=\"Email\" value={email} onChange={setEmail} />\n  </form>\n</Drawer>`;\n\nconst CustomContent: React.FC = () => {\n    const [open, setOpen] = useState(false);\n    const [name, setName] = useState('John Doe');\n    const [email, setEmail] = useState('john@example.com');\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Custom Header & Footer\"\n                description=\"A drawer with a form, custom header, and action buttons in the footer.\"\n            >\n                <Button variant=\"primary\" onClick={() => setOpen(true)}>\n                    Edit Profile\n                </Button>\n            </ComponentDemo>\n            <Drawer\n                open={open}\n                onClose={() => setOpen(false)}\n                header=\"Edit Profile\"\n                footer={\n                    <div className=\"flex gap-2 justify-end\">\n                        <Button variant=\"default\" onClick={() => setOpen(false)}>\n                            Cancel\n                        </Button>\n                        <Button\n                            variant=\"primary\"\n                            onClick={() => {\n                                alert(`Saved: ${name}, ${email}`);\n                                setOpen(false);\n                            }}\n                        >\n                            Save\n                        </Button>\n                    </div>\n                }\n                size=\"480px\"\n            >\n                <div className=\"space-y-4\">\n                    <TextInput placeholder=\"Full Name\" value={name} onChange={(e) => setName(e.value)} />\n                    <TextInput placeholder=\"Email\" value={email} onChange={(e) => setEmail(e.value)} />\n                </div>\n            </Drawer>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default CustomContent;\n"
        },
        {
          "title": "Positions",
          "code": "import React, { useState } from 'react';\nimport type { DrawerPosition } from '../../../components';\nimport { Button, Drawer } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { Drawer } from 'fluxo-ui';\nimport type { DrawerPosition } from 'fluxo-ui';\n\n<Drawer open={open} onClose={close} position=\"left\" header=\"Left Drawer\">\n  ...\n</Drawer>\n\n<Drawer open={open} onClose={close} position=\"top\" header=\"Top Drawer\" size=\"300px\">\n  ...\n</Drawer>\n\n<Drawer open={open} onClose={close} position=\"bottom\" header=\"Bottom Drawer\" size=\"300px\">\n  ...\n</Drawer>`;\n\nconst positions: { label: string; position: DrawerPosition; size?: string }[] = [\n    { label: 'Left', position: 'left' },\n    { label: 'Right', position: 'right' },\n    { label: 'Top', position: 'top', size: '300px' },\n    { label: 'Bottom', position: 'bottom', size: '300px' },\n];\n\nconst Positions: React.FC = () => {\n    const [activePosition, setActivePosition] = useState<DrawerPosition | null>(null);\n\n    return (\n        <>\n            <ComponentDemo title=\"Drawer Positions\" description=\"Drawers can slide in from any edge: left, right, top, or bottom.\">\n                <div className=\"flex flex-wrap gap-3\">\n                    {positions.map(({ label, position }) => (\n                        <Button key={position} variant=\"primary\" layout=\"outlined\" onClick={() => setActivePosition(position)}>\n                            {label}\n                        </Button>\n                    ))}\n                </div>\n            </ComponentDemo>\n            {positions.map(({ position, size }) => (\n                <Drawer\n                    key={position}\n                    open={activePosition === position}\n                    onClose={() => setActivePosition(null)}\n                    position={position}\n                    size={size || '400px'}\n                    header={`${position.charAt(0).toUpperCase() + position.slice(1)} Drawer`}\n                >\n                    <p>\n                        This drawer slides in from the <strong>{position}</strong> edge of the screen.\n                    </p>\n                </Drawer>\n            ))}\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default Positions;\n"
        }
      ],
      "props": {
        "drawerProps": {
          "open": {
            "type": "boolean",
            "required": true,
            "description": "Whether the drawer is visible."
          },
          "onClose": {
            "type": "() => void",
            "required": true,
            "description": "Called when the drawer should close."
          },
          "position": {
            "type": "'left' | 'right' | 'top' | 'bottom'",
            "default": "'right'",
            "description": "Edge from which the drawer slides in."
          },
          "size": {
            "type": "string",
            "default": "'400px'",
            "description": "Width (horizontal) or height (vertical) of the drawer. Ignored when snapPoints is provided."
          },
          "variant": {
            "type": "'panel' | 'sheet'",
            "description": "Visual variant. 'sheet' adds rounded top corners, drag handle, and drag-to-dismiss behavior — ideal for mobile bottom sheets. Auto-resolves to 'sheet' when position='bottom' and any sheet feature is set."
          },
          "showDragHandle": {
            "type": "boolean",
            "description": "Show a drag handle at the top of the drawer. Defaults to true for sheet variant on top/bottom positions."
          },
          "draggable": {
            "type": "boolean",
            "description": "Enable drag-to-dismiss / drag-between-snap-points gestures. Defaults to true for sheet variant on top/bottom positions."
          },
          "snapPoints": {
            "type": "(number | string)[]",
            "description": "List of snap point heights (e.g. [0.3, 0.6, 0.9] or ['30%', '60vh', '600px']). Numeric <=1 is treated as a viewport ratio."
          },
          "initialSnap": {
            "type": "number",
            "default": "0",
            "description": "Index of the snap point used when the drawer opens."
          },
          "onSnapChange": {
            "type": "(index: number) => void",
            "description": "Called when the drawer settles on a new snap point."
          },
          "rounded": {
            "type": "boolean",
            "description": "Round the corners that face the viewport center. Defaults to true for the sheet variant."
          },
          "backdrop": {
            "type": "boolean",
            "default": "true",
            "description": "Show a dark backdrop behind the drawer."
          },
          "pushContent": {
            "type": "boolean",
            "default": "false",
            "description": "Push the main content instead of overlaying."
          },
          "pushContentSelector": {
            "type": "string",
            "description": "CSS selector for the element to push when pushContent is enabled. Defaults to '#root' or the first body child."
          },
          "closeOnEscape": {
            "type": "boolean",
            "default": "true",
            "description": "Close drawer on Escape key press."
          },
          "closeOnBackdropClick": {
            "type": "boolean",
            "default": "true",
            "description": "Close drawer when clicking the backdrop."
          },
          "title": {
            "type": "string",
            "description": "Plain-text title rendered as the drawer header (when no custom header is supplied) and used as the dialog's accessible name."
          },
          "ariaLabel": {
            "type": "string",
            "description": "Accessible name for the dialog. Use when there's no visible title."
          },
          "ariaLabelledBy": {
            "type": "string",
            "description": "ID of an element that labels the dialog. Overrides ariaLabel/title when set."
          },
          "header": {
            "type": "ReactNode",
            "description": "Header content. When provided, shows a header bar with close button."
          },
          "footer": {
            "type": "ReactNode",
            "description": "Footer content rendered at the bottom."
          },
          "children": {
            "type": "ReactNode",
            "required": true,
            "description": "Main body content of the drawer."
          },
          "className": {
            "type": "string",
            "description": "Additional CSS class for the drawer panel."
          }
        }
      },
      "storyDir": "drawer"
    },
    "EmptyState": {
      "name": "EmptyState",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React from 'react';\nimport { EmptyState } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { EmptyState } from 'fluxo-ui';\n\n<EmptyState\n  title=\"No items yet\"\n  description=\"Get started by creating your first item.\"\n  action={{ label: 'Create item', onClick: () => {} }}\n  secondaryAction={{ label: 'Learn more', href: '#' }}\n/>`;\n\nconst BasicUsage: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Default Empty State\" description=\"Title + description + primary and secondary actions.\">\n            <EmptyState\n                title=\"No items yet\"\n                description=\"Get started by creating your first item.\"\n                action={{ label: 'Create item', onClick: () => alert('Create clicked') }}\n                secondaryAction={{ label: 'Learn more', onClick: () => alert('Learn clicked') }}\n            />\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default BasicUsage;\n"
        },
        {
          "title": "Layouts",
          "code": "import React from 'react';\nimport { EmptyState } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<EmptyState layout=\"vertical\" title=\"No items\" />\n<EmptyState layout=\"horizontal\" title=\"No items\" />`;\n\nconst Layouts: React.FC = () => (\n    <>\n        <ComponentDemo\n            title=\"Vertical & Horizontal\"\n            description=\"Vertical centers content; horizontal places the visual on the left and the text/actions on the right (collapses to vertical on narrow viewports).\"\n        >\n            <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 24 }}>\n                <div style={{ border: '1px solid var(--eui-border-subtle)', borderRadius: 8 }}>\n                    <EmptyState\n                        layout=\"vertical\"\n                        size=\"md\"\n                        title=\"No documents yet\"\n                        description=\"Upload a file or create a new document to get started.\"\n                        action={{ label: 'Upload', onClick: () => {} }}\n                    />\n                </div>\n                <div style={{ border: '1px solid var(--eui-border-subtle)', borderRadius: 8 }}>\n                    <EmptyState\n                        layout=\"horizontal\"\n                        size=\"md\"\n                        title=\"Inbox zero\"\n                        description=\"You're all caught up! Check back later for new messages.\"\n                        variant=\"success\"\n                        action={{ label: 'Refresh', onClick: () => {} }}\n                        secondaryAction={{ label: 'Help', onClick: () => {} }}\n                    />\n                </div>\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default Layouts;\n"
        },
        {
          "title": "Sizes",
          "code": "import React from 'react';\nimport { EmptyState, EmptyStateSize } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<EmptyState size=\"sm\" title=\"Compact\" />\n<EmptyState size=\"md\" title=\"Comfortable\" />\n<EmptyState size=\"lg\" title=\"Spacious\" />`;\n\nconst sizes: EmptyStateSize[] = ['sm', 'md', 'lg'];\n\nconst Sizes: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Sizes\" description=\"Three sizes scale the icon, padding, and typography proportionally.\">\n            <div style={{ display: 'flex', gap: 16, flexDirection: 'column', width: '100%' }}>\n                {sizes.map((s) => (\n                    <div key={s} style={{ border: '1px solid var(--eui-border-subtle)', borderRadius: 8 }}>\n                        <EmptyState\n                            size={s}\n                            title={`Size: ${s}`}\n                            description=\"A short description that adapts to the chosen size.\"\n                            action={{ label: 'Action', onClick: () => {} }}\n                        />\n                    </div>\n                ))}\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default Sizes;\n"
        },
        {
          "title": "Variants",
          "code": "import React from 'react';\nimport { EmptyState, EmptyStateVariant } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<EmptyState variant=\"default\" title=\"No items yet\" description=\"Get started by creating one.\" />\n<EmptyState variant=\"noResults\" title=\"No matches\" description=\"Try a different search term.\" />\n<EmptyState variant=\"error\" title=\"Something went wrong\" description=\"We couldn't load your data.\" action={{ label: 'Retry', onClick: () => {} }} />\n<EmptyState variant=\"success\" title=\"All caught up!\" description=\"You're all set for the day.\" />\n<EmptyState variant=\"restricted\" title=\"Access denied\" description=\"You don't have permission to view this.\" />\n<EmptyState variant=\"info\" title=\"Heads up\" description=\"This is an informational state.\" />`;\n\nconst variants: { variant: EmptyStateVariant; title: string; description: string }[] = [\n    { variant: 'default', title: 'No items yet', description: 'Get started by creating one.' },\n    { variant: 'noResults', title: 'No matches', description: 'Try a different search term.' },\n    { variant: 'error', title: 'Something went wrong', description: \"We couldn't load your data.\" },\n    { variant: 'success', title: 'All caught up!', description: \"You're all set for the day.\" },\n    { variant: 'restricted', title: 'Access denied', description: \"You don't have permission to view this.\" },\n    { variant: 'info', title: 'Heads up', description: 'This is an informational state.' },\n];\n\nconst Variants: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Variants\" description=\"Six pre-styled variants pick sensible default icons and tones.\">\n            <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(280px, 1fr))', gap: 16, width: '100%' }}>\n                {variants.map((v) => (\n                    <div\n                        key={v.variant}\n                        style={{\n                            border: '1px solid var(--eui-border-subtle)',\n                            borderRadius: 8,\n                            background: 'var(--eui-bg-subtle)',\n                        }}\n                    >\n                        <EmptyState\n                            variant={v.variant}\n                            size=\"sm\"\n                            title={v.title}\n                            description={v.description}\n                            action={\n                                v.variant === 'error'\n                                    ? { label: 'Retry', onClick: () => {} }\n                                    : v.variant === 'noResults'\n                                      ? { label: 'Reset filters', onClick: () => {} }\n                                      : undefined\n                            }\n                        />\n                    </div>\n                ))}\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default Variants;\n"
        },
        {
          "title": "WithIllustration",
          "code": "import React from 'react';\nimport { EmptyState } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<EmptyState\n  title=\"Custom illustration\"\n  description=\"Replace the icon with any ReactNode.\"\n  illustration={\n    <svg viewBox=\"0 0 200 160\" xmlns=\"http://www.w3.org/2000/svg\">\n      <circle cx=\"100\" cy=\"80\" r=\"50\" fill=\"var(--eui-primary-subtle)\" stroke=\"var(--eui-primary-border)\" />\n      <path d=\"M70 75 L90 95 L130 60\" stroke=\"var(--eui-primary)\" strokeWidth=\"6\" fill=\"none\" />\n    </svg>\n  }\n  action={{ label: 'Get started', onClick: () => {} }}\n/>`;\n\nconst Illustration = () => (\n    <svg viewBox=\"0 0 200 160\" width=\"200\" xmlns=\"http://www.w3.org/2000/svg\">\n        <defs>\n            <linearGradient id=\"es-bg\" x1=\"0%\" y1=\"0%\" x2=\"100%\" y2=\"100%\">\n                <stop offset=\"0%\" stopColor=\"var(--eui-primary-subtle)\" />\n                <stop offset=\"100%\" stopColor=\"var(--eui-bg-subtle)\" />\n            </linearGradient>\n        </defs>\n        <rect x=\"20\" y=\"20\" width=\"160\" height=\"120\" rx=\"14\" fill=\"url(#es-bg)\" stroke=\"var(--eui-border-subtle)\" />\n        <circle cx=\"80\" cy=\"80\" r=\"22\" fill=\"var(--eui-primary-subtle)\" stroke=\"var(--eui-primary-border)\" />\n        <rect x=\"115\" y=\"65\" width=\"50\" height=\"8\" rx=\"4\" fill=\"var(--eui-border-subtle)\" />\n        <rect x=\"115\" y=\"80\" width=\"40\" height=\"8\" rx=\"4\" fill=\"var(--eui-border-subtle)\" />\n        <rect x=\"115\" y=\"95\" width=\"35\" height=\"8\" rx=\"4\" fill=\"var(--eui-border-subtle)\" />\n    </svg>\n);\n\nconst WithIllustration: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Custom Illustration\" description=\"Pass any ReactNode as the illustration slot.\">\n            <EmptyState\n                title=\"Nothing to show — yet\"\n                description=\"Connect a data source to start exploring metrics, charts, and insights.\"\n                illustration={<Illustration />}\n                action={{ label: 'Connect a source', variant: 'primary', onClick: () => {} }}\n                secondaryAction={{ label: 'Watch demo', onClick: () => {} }}\n            />\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default WithIllustration;\n"
        }
      ],
      "props": {
        "emptyStateProps": {
          "title": {
            "type": "string",
            "required": true,
            "description": "Heading text"
          },
          "description": {
            "type": "string | ReactNode",
            "description": "Supporting text below the title"
          },
          "icon": {
            "type": "IconComponent | ReactElement",
            "description": "Small leading icon (overrides the variant default)"
          },
          "illustration": {
            "type": "ReactNode",
            "description": "Large slot for an illustration or image. Replaces the icon when both are set"
          },
          "action": {
            "type": "{ label, onClick?, variant?, loading?, disabled?, href? }",
            "description": "Primary action rendered as a Button"
          },
          "secondaryAction": {
            "type": "{ label, onClick?, variant?, href? }",
            "description": "Secondary action rendered as a plain Button"
          },
          "layout": {
            "type": "'vertical' | 'horizontal'",
            "default": "'vertical'",
            "description": "Vertical centers content; horizontal places illustration left and text/action right (collapses on narrow viewports)"
          },
          "size": {
            "type": "'sm' | 'md' | 'lg'",
            "default": "'md'",
            "description": "Controls overall scale (font sizes, illustration max-width, padding)"
          },
          "variant": {
            "type": "'default' | 'noResults' | 'error' | 'success' | 'restricted' | 'info'",
            "default": "'default'",
            "description": "Picks default icons and colors when neither icon nor illustration is provided"
          },
          "id": {
            "type": "string",
            "description": "HTML id attribute"
          },
          "className": {
            "type": "string",
            "description": "Additional CSS classes"
          },
          "headingLevel": {
            "type": "1 | 2 | 3 | 4 | 5 | 6",
            "default": "3",
            "description": "Controls the heading tag for the title to fit the document outline"
          }
        }
      },
      "storyDir": "empty-state"
    },
    "FileBrowser": {
      "name": "FileBrowser",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React, { useState } from 'react';\nimport { Button, FileBrowser } from '../../../components';\nimport type { FileBrowserView } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { sampleFiles } from './file-browser-story-data';\n\nconst code = `import { FileBrowser } from 'fluxo-ui';\nimport type { FileBrowserItem, FileBrowserView } from 'fluxo-ui';\n\nconst [selected, setSelected] = useState<string[]>([]);\nconst [view, setView] = useState<FileBrowserView>('thumbnail');\n\n<FileBrowser\n    items={files}\n    view={view}\n    onViewChange={setView}\n    showViewSwitcher\n    selectedIds={selected}\n    onSelectionChange={setSelected}\n    videoPreview\n    onItemOpen={(item) => console.log('open', item.name)}\n    renderActions={(item) => <Button label=\"Open\" size=\"xs\" layout=\"plain\" />}\n/>`;\n\nconst BasicUsage: React.FC = () => {\n    const [selected, setSelected] = useState<string[]>([]);\n    const [view, setView] = useState<FileBrowserView>('thumbnail');\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Files in thumbnail, list and details views\"\n                description=\"A selectable browser with file-kind icons, image/video thumbnails, inline video playback, per-item actions and full keyboard navigation. Toggle the view from the toolbar.\"\n            >\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16 }}>\n                    <FileBrowser\n                        items={sampleFiles}\n                        view={view}\n                        onViewChange={setView}\n                        showViewSwitcher\n                        selectedIds={selected}\n                        onSelectionChange={setSelected}\n                        videoPreview\n                        renderActions={() => <Button label=\"Open\" size=\"xs\" layout=\"plain\" />}\n                    />\n                    <div\n                        style={{\n                            padding: '12px 16px',\n                            background: 'var(--eui-bg-subtle)',\n                            border: '1px solid var(--eui-border-subtle)',\n                            borderRadius: 6,\n                            color: 'var(--eui-text)',\n                        }}\n                    >\n                        View: <strong>{view}</strong> · Selected:{' '}\n                        <strong>{selected.length ? selected.join(', ') : 'none'}</strong>\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "FolderNavigation",
          "code": "import React, { useMemo, useState } from 'react';\nimport { Breadcrumb, FileBrowser } from '../../../components';\nimport type { FileBrowserItem } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\ninterface Node extends FileBrowserItem {\n    children?: Node[];\n}\n\nconst tree: Node[] = [\n    {\n        id: 'photos',\n        name: 'Photos',\n        kind: 'folder',\n        children: [\n            { id: 'p1', name: 'beach.jpg', kind: 'image', thumbnailUrl: 'https://picsum.photos/seed/fb-n1/240/180', size: 320000 },\n            { id: 'p2', name: 'forest.jpg', kind: 'image', thumbnailUrl: 'https://picsum.photos/seed/fb-n2/240/180', size: 280000 },\n        ],\n    },\n    {\n        id: 'docs',\n        name: 'Documents',\n        kind: 'folder',\n        children: [\n            { id: 'd1', name: 'invoice.pdf', kind: 'pdf', size: 90000 },\n            { id: 'd2', name: 'notes.txt', kind: 'text', size: 2048 },\n        ],\n    },\n    { id: 'r1', name: 'readme.md', kind: 'text', size: 1024 },\n];\n\nconst code = `const [path, setPath] = useState<string[]>([]);\n\n<FileBrowser\n    view=\"details\"\n    items={currentItems}\n    toolbarStart={<Breadcrumb items={crumbs} onItemClick={navigate} />}\n    onItemOpen={(item) => {\n        if (item.kind === 'folder') setPath((p) => [...p, item.id]);\n    }}\n/>`;\n\nfunction findChildren(path: string[]): Node[] {\n    let level = tree;\n    for (const id of path) {\n        const next = level.find((n) => n.id === id)?.children;\n        if (!next) return [];\n        level = next;\n    }\n    return level;\n}\n\nconst FolderNavigation: React.FC = () => {\n    const [path, setPath] = useState<string[]>([]);\n    const items = useMemo(() => findChildren(path), [path]);\n\n    const crumbs = useMemo(() => {\n        const out = [{ label: 'Home', value: '' }];\n        let level = tree;\n        for (const id of path) {\n            const node = level.find((n) => n.id === id);\n            if (!node) break;\n            out.push({ label: node.name, value: id });\n            level = node.children ?? [];\n        }\n        return out;\n    }, [path]);\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Folder navigation\"\n                description=\"Open a folder with Enter or double-click to drill in; the breadcrumb in the toolbar walks back out. The same pattern powers Google Drive / OneDrive style explorers.\"\n            >\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16 }}>\n                    <FileBrowser\n                        view=\"details\"\n                        items={items}\n                        ariaLabel=\"Folder contents\"\n                        selectable={false}\n                        emptyState={<span style={{ color: 'var(--eui-text-muted)' }}>This folder is empty</span>}\n                        toolbarStart={\n                            <Breadcrumb\n                                items={crumbs.map((c) => ({ label: c.label }))}\n                                onItemClick={(_item, index) => setPath(path.slice(0, index))}\n                            />\n                        }\n                        onItemOpen={(item) => {\n                            if (item.kind === 'folder') setPath((p) => [...p, item.id]);\n                        }}\n                    />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default FolderNavigation;\n"
        },
        {
          "title": "UploadAndFilters",
          "code": "import React, { useState } from 'react';\nimport { FileBrowser } from '../../../components';\nimport type { FileBrowserItem, RejectedFile } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { FileBrowser } from 'fluxo-ui';\nimport type { FileBrowserItem, RejectedFile } from 'fluxo-ui';\n\n<FileBrowser\n    items={items}\n    enableUpload\n    multiple\n    accept=\"image/*,.pdf\"\n    maxFileSize={5 * 1024 * 1024}\n    maxSelection={8}\n    uploadHint=\"Drop images or PDFs (max 5 MB)\"\n    onUpload={(accepted, rejected) => {\n        addFiles(accepted);\n        rejected.forEach((r) => console.warn(r.file.name, 'rejected:', r.reason));\n    }}\n/>`;\n\nconst UploadAndFilters: React.FC = () => {\n    const [items, setItems] = useState<FileBrowserItem[]>([]);\n    const [log, setLog] = useState<string>('Drop or pick files (images / PDFs, max 5 MB, up to 8).');\n\n    const onUpload = (accepted: File[], rejected: RejectedFile[]) => {\n        const next = accepted.map<FileBrowserItem>((file) => ({\n            id: `${file.name}-${file.size}-${file.lastModified}`,\n            name: file.name,\n            mimeType: file.type,\n            size: file.size,\n            thumbnailUrl: file.type.startsWith('image/') ? URL.createObjectURL(file) : undefined,\n            previewUrl: file.type.startsWith('video/') ? URL.createObjectURL(file) : undefined,\n        }));\n        setItems((prev) => {\n            const existing = new Set(prev.map((p) => p.id));\n            return [...prev, ...next.filter((n) => !existing.has(n.id))];\n        });\n        const parts: string[] = [];\n        if (accepted.length) parts.push(`${accepted.length} accepted`);\n        if (rejected.length) {\n            const reasons = rejected.map((r) => `${r.file.name} (${r.reason})`).join(', ');\n            parts.push(`${rejected.length} rejected: ${reasons}`);\n        }\n        setLog(parts.join(' · ') || 'No files.');\n    };\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Drag-and-drop upload with type, size and count filters\"\n                description=\"Drop files anywhere on the browser, or use the empty-state button. accept, maxFileSize and maxSelection reject files and report why.\"\n            >\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16 }}>\n                    <FileBrowser\n                        items={items}\n                        enableUpload\n                        multiple\n                        accept=\"image/*,.pdf\"\n                        maxFileSize={5 * 1024 * 1024}\n                        maxSelection={8}\n                        uploadHint=\"Drop images or PDFs (max 5 MB)\"\n                        onUpload={onUpload}\n                        style={{ minHeight: 220 }}\n                    />\n                    <div\n                        style={{\n                            padding: '12px 16px',\n                            background: 'var(--eui-bg-subtle)',\n                            border: '1px solid var(--eui-border-subtle)',\n                            borderRadius: 6,\n                            color: 'var(--eui-text)',\n                            fontSize: 13,\n                        }}\n                    >\n                        {log}\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default UploadAndFilters;\n"
        }
      ],
      "props": {
        "fileBrowserProps": {
          "items": {
            "type": "FileBrowserItem[]",
            "required": true,
            "description": "Items to render. Each: { id, name, kind?, subtitle?, thumbnailUrl?, previewUrl?, mimeType?, size?, modified?, badge?, loading?, disabled?, selectable?, meta?, data? }. When kind is omitted it is inferred from mimeType then the file extension."
          },
          "selectedIds": {
            "type": "string[]",
            "description": "Controlled selected ids. Omit to let the component manage selection internally."
          },
          "onSelectionChange": {
            "type": "(ids: string[]) => void",
            "description": "Called whenever the selection changes."
          },
          "view": {
            "type": "'thumbnail' | 'list' | 'details'",
            "description": "Controlled view. Omit to use defaultView and internal state."
          },
          "defaultView": {
            "type": "'thumbnail' | 'list' | 'details'",
            "default": "'thumbnail'",
            "description": "Initial view when uncontrolled."
          },
          "onViewChange": {
            "type": "(view: FileBrowserView) => void",
            "description": "Called when the view changes via the switcher."
          },
          "availableViews": {
            "type": "FileBrowserView[]",
            "default": "['thumbnail', 'list', 'details']",
            "description": "Which views the built-in switcher offers."
          },
          "showViewSwitcher": {
            "type": "boolean",
            "default": "false",
            "description": "Render the built-in thumbnail/list/details toggle in the toolbar."
          },
          "selectable": {
            "type": "boolean",
            "default": "true",
            "description": "Whether items can be selected."
          },
          "multiple": {
            "type": "boolean",
            "default": "true",
            "description": "Allow selecting more than one item. Also controls whether the upload picker accepts multiple files."
          },
          "maxSelection": {
            "type": "number",
            "description": "Maximum number of items selectable at once when multiple. Also caps how many dropped/picked files are accepted for upload."
          },
          "thumbnailFit": {
            "type": "'cover' | 'contain'",
            "default": "'contain'",
            "description": "How each image/video thumbnail fits its box."
          },
          "minTileWidth": {
            "type": "number",
            "default": "160",
            "description": "Minimum tile width in px for the thumbnail grid."
          },
          "columns": {
            "type": "FileBrowserColumn[]",
            "default": "name / type / size / modified",
            "description": "Columns rendered in the details view. Each: { key, header, width?, align?, render? }. The 'name' column auto-grows and shows the kind icon; built-in keys size/modified/kind format automatically, others read item.meta[key]."
          },
          "emptyState": {
            "type": "React.ReactNode",
            "description": "Custom content shown when there are no items."
          },
          "renderActions": {
            "type": "(item: FileBrowserItem) => React.ReactNode",
            "description": "Render per-item action buttons (preview, edit, remove, download…). Shown on hover in thumbnail/list and inline in details."
          },
          "renderPreview": {
            "type": "(item: FileBrowserItem, kind: FileKind) => React.ReactNode",
            "description": "Override the default thumbnail/preview rendering for an item entirely."
          },
          "renderItem": {
            "type": "(item: FileBrowserItem, ctx: FileBrowserItemContext) => React.ReactNode",
            "description": "Fully override the tile body in thumbnail/list views. ctx exposes { kind, selected, view, toggle, open }."
          },
          "onItemOpen": {
            "type": "(item: FileBrowserItem) => void",
            "description": "Called on Enter or double-click — use for folder navigation or opening a preview."
          },
          "onItemClick": {
            "type": "(item: FileBrowserItem) => void",
            "description": "Called on single click, before selection toggles."
          },
          "videoPreview": {
            "type": "boolean",
            "default": "false",
            "description": "Play video items inline (with controls) when their thumbnail is clicked. Falls back to a poster image with a play overlay."
          },
          "enableUpload": {
            "type": "boolean",
            "default": "false",
            "description": "Enable drag-and-drop file upload onto the browser and a hidden file input opened via the empty-state button."
          },
          "accept": {
            "type": "string",
            "description": "Comma-separated accept list applied to uploads (e.g. 'image/*,.pdf'). Files not matching are rejected with reason 'type'."
          },
          "maxFileSize": {
            "type": "number",
            "description": "Maximum size in bytes for an uploaded file. Larger files are rejected with reason 'size'."
          },
          "onUpload": {
            "type": "(files: File[], rejected: RejectedFile[]) => void",
            "description": "Called after a drop or pick with the accepted files and the rejected ones (each carrying reason 'type' | 'size' | 'count')."
          },
          "uploadHint": {
            "type": "React.ReactNode",
            "description": "Message shown in the drop overlay while dragging files over the browser."
          },
          "className": {
            "type": "string",
            "description": "Additional class for the container."
          },
          "style": {
            "type": "React.CSSProperties",
            "description": "Inline styles for the outer container (e.g. a minHeight so the drop zone stays usable when empty)."
          },
          "ariaLabel": {
            "type": "string",
            "default": "'Files'",
            "description": "Accessible label for the collection/grid container."
          },
          "toolbarStart": {
            "type": "React.ReactNode",
            "description": "Custom content rendered at the start of the toolbar (e.g. breadcrumb, search)."
          },
          "toolbarEnd": {
            "type": "React.ReactNode",
            "description": "Custom content rendered at the end of the toolbar, before the view switcher."
          }
        }
      },
      "storyDir": "file-browser"
    },
    "FileUpload": {
      "name": "FileUpload",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React from 'react';\nimport { FileUpload } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { FileUpload } from 'fluxo-ui';\n\n<FileUpload\n  accept=\"image/*\"\n  multiple\n  maxFileSize={5 * 1024 * 1024}\n  maxFiles={5}\n  showPreview\n  onFilesSelect={(files) => console.log('Selected:', files)}\n  onUpload={async (file, onProgress) => {\n    for (let i = 0; i <= 100; i += 10) {\n      await new Promise((r) => setTimeout(r, 200));\n      onProgress(i);\n    }\n  }}\n/>`;\n\nconst simulateUpload = async (_file: File, onProgress: (percent: number) => void) => {\n    for (let i = 0; i <= 100; i += 10) {\n        await new Promise((r) => setTimeout(r, 200));\n        onProgress(i);\n    }\n};\n\nconst BasicUsage: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Image Upload\" description=\"Drag and drop or click to upload images with progress tracking and preview.\">\n            <div className=\"w-full max-w-lg\">\n                <FileUpload\n                    accept=\"image/*\"\n                    multiple\n                    maxFileSize={5 * 1024 * 1024}\n                    maxFiles={5}\n                    showPreview\n                    onFilesSelect={(files) => console.log('Selected:', files)}\n                    onUpload={simulateUpload}\n                />\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default BasicUsage;\n"
        },
        {
          "title": "ImagePreview",
          "code": "import React from 'react';\nimport { FileUpload } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst simulateUpload = async (_file: File, onProgress: (percent: number) => void) => {\n    for (let i = 0; i <= 100; i += 20) {\n        await new Promise((r) => setTimeout(r, 300));\n        onProgress(i);\n    }\n};\n\nconst code = `import { FileUpload } from 'fluxo-ui';\n\n<FileUpload\n  accept=\"image/*\"\n  multiple\n  maxFiles={4}\n  showPreview\n  onUpload={async (file, onProgress) => {\n    // simulate upload\n    for (let i = 0; i <= 100; i += 20) {\n      await new Promise((r) => setTimeout(r, 300));\n      onProgress(i);\n    }\n  }}\n/>`;\n\nconst ImagePreview: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Image Preview\" description=\"Uploaded images show thumbnail previews with progress bars during upload.\">\n            <div className=\"w-full max-w-lg\">\n                <FileUpload accept=\"image/*\" multiple maxFiles={4} showPreview onUpload={simulateUpload} />\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default ImagePreview;\n"
        },
        {
          "title": "Validation",
          "code": "import React from 'react';\nimport { FileUpload } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst customValidator = (file: File): string | undefined => {\n    if (file.name.includes(' ')) {\n        return 'File name must not contain spaces';\n    }\n    return undefined;\n};\n\nconst code = `import { FileUpload } from 'fluxo-ui';\n\n<FileUpload\n  accept=\".pdf,.doc,.docx\"\n  multiple\n  maxFileSize={2 * 1024 * 1024}\n  maxFiles={3}\n  customValidator={(file) => {\n    if (file.name.includes(' ')) {\n      return 'File name must not contain spaces';\n    }\n    return undefined;\n  }}\n  onFilesSelect={(files) => console.log('Valid files:', files)}\n/>`;\n\nconst Validation: React.FC = () => (\n    <>\n        <ComponentDemo\n            title=\"File Validation\"\n            description=\"Restrict file types, enforce size limits, and add custom validation rules. Invalid files display inline error messages.\"\n        >\n            <div className=\"w-full max-w-lg\">\n                <FileUpload\n                    accept=\".pdf,.doc,.docx\"\n                    multiple\n                    maxFileSize={2 * 1024 * 1024}\n                    maxFiles={3}\n                    showPreview\n                    customValidator={customValidator}\n                    onFilesSelect={(files) => console.log('Valid files:', files)}\n                />\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default Validation;\n"
        }
      ],
      "props": {
        "fileUploadProps": {
          "accept": {
            "type": "string",
            "description": "Accepted file types (e.g. \"image/*\", \".pdf,.doc\")."
          },
          "multiple": {
            "type": "boolean",
            "default": "false",
            "description": "Allow multiple file selection."
          },
          "maxFileSize": {
            "type": "number",
            "description": "Maximum file size in bytes."
          },
          "maxFiles": {
            "type": "number",
            "description": "Maximum number of files allowed."
          },
          "disabled": {
            "type": "boolean",
            "default": "false",
            "description": "Disable the upload zone."
          },
          "showPreview": {
            "type": "boolean",
            "default": "true",
            "description": "Show image previews for uploaded files."
          },
          "dropzoneContent": {
            "type": "ReactNode",
            "description": "Custom content for the dropzone area."
          },
          "onFilesSelect": {
            "type": "(files: File[]) => void",
            "description": "Called when files are selected."
          },
          "onFileRemove": {
            "type": "(file: UploadFile) => void",
            "description": "Called when a file is removed from the list."
          },
          "onUpload": {
            "type": "(file: File, onProgress: (percent: number) => void) => Promise<void>",
            "description": "Upload handler with progress callback."
          },
          "customValidator": {
            "type": "(file: File) => string | undefined",
            "description": "Custom validation function returning an error message."
          },
          "className": {
            "type": "string",
            "description": "Additional CSS class for the container."
          }
        }
      },
      "storyDir": "file-upload"
    },
    "FloatingLabelInput": {
      "name": "FloatingLabelInput",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React, { useState } from 'react';\nimport { FloatingLabelInput } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { FloatingLabelInput } from 'fluxo-ui';\n\n<FloatingLabelInput\n    label=\"Email address\"\n    type=\"email\"\n    value={email}\n    onChange={(e) => setEmail(e.target.value)}\n    helperText=\"We'll never share your email.\"\n/>`;\n\nconst BasicUsage: React.FC = () => {\n    const [email, setEmail] = useState('');\n    return (\n        <>\n            <ComponentDemo title=\"Default outlined input\" description=\"The label floats above the field on focus or when it has a value — saves a full row of label height on mobile screens.\">\n                <div style={{ width: '100%', maxWidth: 360 }}>\n                    <FloatingLabelInput\n                        label=\"Email address\"\n                        type=\"email\"\n                        value={email}\n                        onChange={(e) => setEmail(e.target.value)}\n                        helperText=\"We'll never share your email.\"\n                        fullWidth\n                    />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\"><CodeBlock code={code} language=\"tsx\" /></div>\n        </>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "Sizes",
          "code": "import React from 'react';\nimport { FloatingLabelInput } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<FloatingLabelInput label=\"Small\"  size=\"sm\" />\n<FloatingLabelInput label=\"Medium\" size=\"md\" />\n<FloatingLabelInput label=\"Large\"  size=\"lg\" />`;\n\nconst Sizes: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Three sizes\" description=\"Pair size to surrounding form density. Large is recommended for mobile-first forms.\">\n            <div style={{ width: '100%', maxWidth: 360, display: 'flex', flexDirection: 'column', gap: 12 }}>\n                <FloatingLabelInput fullWidth label=\"Small\" size=\"sm\" />\n                <FloatingLabelInput fullWidth label=\"Medium\" size=\"md\" />\n                <FloatingLabelInput fullWidth label=\"Large\" size=\"lg\" />\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\"><CodeBlock code={code} language=\"tsx\" /></div>\n    </>\n);\n\nexport default Sizes;\n"
        },
        {
          "title": "States",
          "code": "import React, { useState } from 'react';\nimport { FloatingLabelInput } from '../../../components';\nimport { EyeIcon, SearchIcon } from '../../../assets/icons';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<FloatingLabelInput label=\"Search\" leadingIcon={<SearchIcon />} fullWidth />\n<FloatingLabelInput label=\"Email\" type=\"email\" required fullWidth />\n<FloatingLabelInput label=\"Password\" type=\"password\" trailingIcon={<EyeIcon />} fullWidth />\n<FloatingLabelInput label=\"Username\" errorText=\"That handle is taken\" fullWidth />\n<FloatingLabelInput label=\"Read-only\" defaultValue=\"alice@example.com\" disabled fullWidth />`;\n\nconst States: React.FC = () => {\n    const [search, setSearch] = useState('');\n    const [user, setUser] = useState('bob');\n    return (\n        <>\n            <ComponentDemo title=\"Leading & trailing icons\" description=\"Add icons inside the field — labels auto-shift to make room.\">\n                <div style={{ width: '100%', maxWidth: 360, display: 'flex', flexDirection: 'column', gap: 12 }}>\n                    <FloatingLabelInput fullWidth label=\"Search\" leadingIcon={<SearchIcon />} value={search} onChange={(e) => setSearch(e.target.value)} />\n                    <FloatingLabelInput fullWidth label=\"Email\" type=\"email\" required />\n                    <FloatingLabelInput fullWidth label=\"Password\" type=\"password\" trailingIcon={<EyeIcon />} />\n                </div>\n            </ComponentDemo>\n\n            <ComponentDemo title=\"Error state\" description=\"Pass errorText to highlight the field, render the message, and announce it via role=alert.\" className=\"mt-4\">\n                <div style={{ width: '100%', maxWidth: 360 }}>\n                    <FloatingLabelInput fullWidth label=\"Username\" value={user} onChange={(e) => setUser(e.target.value)} errorText=\"That handle is taken\" />\n                </div>\n            </ComponentDemo>\n\n            <ComponentDemo title=\"Disabled\" description=\"Read-only fields fade out the wrapper but keep the label and value visible.\" className=\"mt-4\">\n                <div style={{ width: '100%', maxWidth: 360 }}>\n                    <FloatingLabelInput fullWidth label=\"Email\" defaultValue=\"alice@example.com\" disabled />\n                </div>\n            </ComponentDemo>\n\n            <div className=\"mt-4\"><CodeBlock code={code} language=\"tsx\" /></div>\n        </>\n    );\n};\n\nexport default States;\n"
        },
        {
          "title": "Variants",
          "code": "import React, { useState } from 'react';\nimport { FloatingLabelInput } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<FloatingLabelInput label=\"Outlined\" variant=\"outlined\" />\n<FloatingLabelInput label=\"Filled\" variant=\"filled\" />\n<FloatingLabelInput label=\"Underlined\" variant=\"underlined\" />`;\n\nconst Variants: React.FC = () => {\n    const [out, setOut] = useState('');\n    const [fil, setFil] = useState('');\n    const [und, setUnd] = useState('');\n    return (\n        <>\n            <ComponentDemo title=\"Outlined (default)\" description=\"Borders on all four sides with the floating label cutting through the top border.\">\n                <div style={{ width: '100%', maxWidth: 360 }}><FloatingLabelInput fullWidth label=\"Full name\" variant=\"outlined\" value={out} onChange={(e) => setOut(e.target.value)} /></div>\n            </ComponentDemo>\n            <ComponentDemo title=\"Filled\" description=\"A subtle background fills the field, with only the bottom border visible — a denser, Android-style look.\" className=\"mt-4\">\n                <div style={{ width: '100%', maxWidth: 360 }}><FloatingLabelInput fullWidth label=\"Address line 1\" variant=\"filled\" value={fil} onChange={(e) => setFil(e.target.value)} /></div>\n            </ComponentDemo>\n            <ComponentDemo title=\"Underlined\" description=\"Only the bottom border — works well on transparent surfaces.\" className=\"mt-4\">\n                <div style={{ width: '100%', maxWidth: 360 }}><FloatingLabelInput fullWidth label=\"Pet name\" variant=\"underlined\" value={und} onChange={(e) => setUnd(e.target.value)} /></div>\n            </ComponentDemo>\n            <div className=\"mt-4\"><CodeBlock code={code} language=\"tsx\" /></div>\n        </>\n    );\n};\n\nexport default Variants;\n"
        }
      ],
      "props": {
        "floatingLabelInputProps": {
          "label": {
            "type": "string",
            "required": true,
            "description": "Floating label text shown above the input when focused or filled."
          },
          "value": {
            "type": "string | number",
            "description": "Controlled value."
          },
          "defaultValue": {
            "type": "string | number",
            "description": "Initial value for uncontrolled usage."
          },
          "onChange": {
            "type": "(event: ChangeEvent<HTMLInputElement>) => void",
            "description": "Change handler."
          },
          "helperText": {
            "type": "ReactNode",
            "description": "Helper line shown below the input."
          },
          "errorText": {
            "type": "ReactNode",
            "description": "Error message shown in place of the helper when set. Triggers error styling."
          },
          "variant": {
            "type": "'outlined' | 'filled' | 'underlined'",
            "default": "'outlined'",
            "description": "Visual style. 'filled' uses a subtle background; 'underlined' shows only the bottom rule."
          },
          "size": {
            "type": "'sm' | 'md' | 'lg'",
            "default": "'md'",
            "description": "Field size."
          },
          "fullWidth": {
            "type": "boolean",
            "default": "false",
            "description": "Stretch to fill its container."
          },
          "leadingIcon": {
            "type": "ReactNode",
            "description": "Icon shown before the input field."
          },
          "trailingIcon": {
            "type": "ReactNode",
            "description": "Icon shown after the input field."
          },
          "invalid": {
            "type": "boolean",
            "default": "false",
            "description": "Force error styling without an error message."
          },
          "rootClassName": {
            "type": "string",
            "description": "Additional CSS class for the wrapper element."
          },
          "className": {
            "type": "string",
            "description": "Additional CSS class for the underlying <input>."
          }
        }
      },
      "storyDir": "floating-label-input"
    },
    "GanttChart": {
      "name": "GanttChart",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import cn from 'classnames';\nimport React from 'react';\nimport { GanttChart } from '../../../components/gantt-chart';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\nimport { basicTasks } from './gantt-chart-story-data';\n\nconst BasicUsage: React.FC = () => {\n    const { isDark } = useStoryTheme();\n\n    return (\n        <>\n            <p className={cn('mb-4 text-sm', { 'text-gray-400': isDark, 'text-gray-500': !isDark })}>\n                A minimal Gantt chart with default columns. Tasks auto-scroll to today on mount.\n            </p>\n            <ComponentDemo title=\"Basic Gantt Chart\" centered={false}>\n                <GanttChart tasks={basicTasks} height={340} />\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock\n                    title=\"Basic Example\"\n                    code={`import { GanttChart } from 'fluxo-ui';\nimport type { GanttTask } from 'fluxo-ui';\n\nconst tasks: GanttTask[] = [\n  {\n    id: '1',\n    name: 'Requirements Gathering',\n    start: new Date('2025-01-01'),\n    end: new Date('2025-01-07'),\n    progress: 100,\n    assignee: 'Alice',\n  },\n  {\n    id: '2',\n    name: 'UI Design',\n    start: new Date('2025-01-06'),\n    end: new Date('2025-01-14'),\n    progress: 60,\n    color: '#8b5cf6',\n    assignee: 'Bob',\n  },\n  // ...\n];\n\nfunction MyPage() {\n  return <GanttChart tasks={tasks} height={400} />;\n}`}\n                />\n            </div>\n        </>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "CustomColumns",
          "code": "import cn from 'classnames';\nimport React from 'react';\nimport { GanttChart } from '../../../components/gantt-chart';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\nimport { basicTasks, customColumns } from './gantt-chart-story-data';\n\nconst CustomColumnsDemo: React.FC = () => {\n    const { isDark } = useStoryTheme();\n\n    return (\n        <>\n            <p className={cn('mb-4 text-sm', { 'text-gray-400': isDark, 'text-gray-500': !isDark })}>\n                Define any number of columns with custom render templates. Access the full task object inside templates.\n            </p>\n            <ComponentDemo title=\"Custom Column Rendering\" centered={false}>\n                <GanttChart tasks={basicTasks} height={340} columns={customColumns} fieldsPanelWidth={370} />\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock\n                    code={`import type { GanttColumn } from 'fluxo-ui';\n\nconst columns: GanttColumn[] = [\n  { field: 'name', headerText: 'Task', width: 200 },\n  {\n    field: 'assignee',\n    headerText: 'Owner',\n    width: 90,\n    align: 'center',\n    template: ({ value }) => (\n      <span style={{\n        display: 'inline-flex', alignItems: 'center', justifyContent: 'center',\n        width: 26, height: 26, borderRadius: '50%',\n        background: '#dbeafe', color: '#1d4ed8', fontWeight: 600, fontSize: 11,\n      }}>\n        {String(value ?? '?').charAt(0)}\n      </span>\n    ),\n  },\n  {\n    field: 'progress',\n    headerText: '%',\n    width: 55,\n    align: 'center',\n    template: ({ value }) => (\n      <span style={{ color: value === 100 ? '#10b981' : '#6b7280', fontWeight: 600 }}>\n        {value}%\n      </span>\n    ),\n  },\n];\n\n<GanttChart tasks={tasks} columns={columns} fieldsPanelWidth={360} height={400} />`}\n                />\n            </div>\n        </>\n    );\n};\n\nexport default CustomColumnsDemo;\n"
        },
        {
          "title": "DateMarkers",
          "code": "import cn from 'classnames';\nimport React from 'react';\nimport { GanttChart } from '../../../components/gantt-chart';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\nimport { basicTasks, markers } from './gantt-chart-story-data';\n\nconst DateMarkers: React.FC = () => {\n    const { isDark } = useStoryTheme();\n\n    return (\n        <>\n            <p className={cn('mb-4 text-sm', { 'text-gray-400': isDark, 'text-gray-500': !isDark })}>\n                Mark important dates (sprint boundaries, deadlines, releases) with labelled vertical lines.\n            </p>\n            <ComponentDemo title=\"Markers &amp; Deadlines\" centered={false}>\n                <GanttChart tasks={basicTasks} height={340} markers={markers} />\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock\n                    code={`import type { GanttMarker } from 'fluxo-ui';\n\nconst markers: GanttMarker[] = [\n  { id: 'today',    date: new Date(),               label: 'Today',      color: '#3b82f6' },\n  { id: 'sprint',   date: new Date('2025-02-07'),   label: 'Sprint End', color: '#f59e0b' },\n  { id: 'release',  date: new Date('2025-02-28'),   label: 'Release',    color: '#10b981' },\n];\n\n<GanttChart tasks={tasks} markers={markers} height={400} />`}\n                />\n            </div>\n        </>\n    );\n};\n\nexport default DateMarkers;\n"
        },
        {
          "title": "Dependencies",
          "code": "import cn from 'classnames';\nimport React from 'react';\nimport { GanttChart } from '../../../components/gantt-chart';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\nimport { dependencyTasks } from './gantt-chart-story-data';\n\nconst Dependencies: React.FC = () => {\n    const { isDark } = useStoryTheme();\n\n    return (\n        <>\n            <p className={cn('mb-4 text-sm', { 'text-gray-400': isDark, 'text-gray-500': !isDark })}>\n                Connect tasks with dependency arrows using four relationship types: Finish-to-Start, Start-to-Start, Finish-to-Finish, and Start-to-Finish.\n            </p>\n            <ComponentDemo title=\"Dependency Arrows\" centered={false}>\n                <GanttChart\n                    tasks={dependencyTasks}\n                    height={340}\n                    columns={[{ field: 'name', headerText: 'Task', width: 200 }]}\n                />\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock\n                    code={`const tasks: GanttTask[] = [\n  {\n    id: 'analysis',\n    name: 'Analysis',\n    start: '2025-01-01',\n    end: '2025-01-07',\n    progress: 100,\n  },\n  {\n    id: 'design',\n    name: 'Design',\n    start: '2025-01-08',\n    end: '2025-01-14',\n    progress: 60,\n    dependencies: [{ targetId: 'analysis', type: 'finish-to-start' }],\n  },\n  {\n    id: 'dev',\n    name: 'Development',\n    start: '2025-01-15',\n    end: '2025-01-28',\n    progress: 0,\n    dependencies: [{ targetId: 'design', type: 'finish-to-start' }],\n  },\n];\n\n// Supported dependency types:\n// 'finish-to-start' | 'start-to-start' | 'finish-to-finish' | 'start-to-finish'`}\n                />\n            </div>\n        </>\n    );\n};\n\nexport default Dependencies;\n"
        },
        {
          "title": "DragAndDrop",
          "code": "import cn from 'classnames';\nimport React, { useState } from 'react';\nimport { GanttChart } from '../../../components/gantt-chart';\nimport type { GanttTask, GanttTaskChangeEvent, GanttTaskClickEvent } from '../../../components/gantt-chart';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\nimport { basicTasks } from './gantt-chart-story-data';\n\nconst DragAndDrop: React.FC = () => {\n    const { isDark } = useStoryTheme();\n    const [interactiveTasks, setInteractiveTasks] = useState<GanttTask[]>(basicTasks);\n    const [lastEvent, setLastEvent] = useState<string>('');\n    const [selectedTask, setSelectedTask] = useState<GanttTask | null>(null);\n\n    const handleTaskChange = (e: GanttTaskChangeEvent) => {\n        setInteractiveTasks(prev =>\n            prev.map(t => t.id === e.task.id ? { ...t, start: e.start, end: e.end } : t)\n        );\n        setLastEvent(`Moved \"${e.originalTask.name}\" → ${e.start.toLocaleDateString()} – ${e.end.toLocaleDateString()}`);\n    };\n\n    const handleTaskClick = (e: GanttTaskClickEvent) => {\n        setSelectedTask(e.task);\n        setLastEvent(`Clicked: \"${e.task.name}\"`);\n    };\n\n    return (\n        <>\n            <p className={cn('mb-4 text-sm', { 'text-gray-400': isDark, 'text-gray-500': !isDark })}>\n                Drag task bars to move them or drag either handle to resize. Changes are reported via <code>onTaskChange</code>.\n            </p>\n            <ComponentDemo title=\"Interactive — Drag to Move, Handles to Resize\" centered={false}>\n                <div className=\"space-y-3\">\n                    <GanttChart\n                        tasks={interactiveTasks}\n                        height={320}\n                        onTaskChange={handleTaskChange}\n                        onTaskClick={handleTaskClick}\n                    />\n                    {lastEvent && (\n                        <div className={cn('text-sm px-4 py-2 rounded border', {\n                            'border-blue-800 bg-blue-900/30 text-blue-300': isDark,\n                            'border-blue-200 bg-blue-50 text-blue-800': !isDark,\n                        })}>\n                            Event: {lastEvent}\n                        </div>\n                    )}\n                    {selectedTask && (\n                        <div className={cn('text-sm px-4 py-2 rounded border', {\n                            'border-purple-800 bg-purple-900/30 text-purple-300': isDark,\n                            'border-purple-200 bg-purple-50 text-purple-800': !isDark,\n                        })}>\n                            Selected: <strong>{selectedTask.name}</strong> — Progress: {selectedTask.progress ?? 0}%\n                        </div>\n                    )}\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock\n                    code={`const [tasks, setTasks] = useState<GanttTask[]>(initialTasks);\n\nconst handleTaskChange = (e: GanttTaskChangeEvent) => {\n  setTasks(prev =>\n    prev.map(t => t.id === e.task.id\n      ? { ...t, start: e.start, end: e.end }\n      : t\n    )\n  );\n};\n\n<GanttChart\n  tasks={tasks}\n  height={400}\n  allowTaskDrag={true}     // default\n  allowTaskResize={true}   // default\n  onTaskChange={handleTaskChange}\n  onTaskClick={({ task }) => console.log('clicked', task.name)}\n  onTaskDoubleClick={({ task }) => openEditModal(task)}\n/>`}\n                />\n            </div>\n        </>\n    );\n};\n\nexport default DragAndDrop;\n"
        },
        {
          "title": "HierarchicalTasks",
          "code": "import cn from 'classnames';\nimport React from 'react';\nimport { GanttChart } from '../../../components/gantt-chart';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\nimport { hierarchicalTasks } from './gantt-chart-story-data';\n\nconst HierarchicalTasks: React.FC = () => {\n    const { isDark } = useStoryTheme();\n\n    return (\n        <>\n            <p className={cn('mb-4 text-sm', { 'text-gray-400': isDark, 'text-gray-500': !isDark })}>\n                Nest child tasks inside a parent using the <code>children</code> array. Use <code>type: 'group'</code> for summary bars and <code>type: 'milestone'</code> for diamond markers. Groups can be collapsed.\n            </p>\n            <ComponentDemo title=\"Phases, Groups &amp; Milestones\" centered={false}>\n                <GanttChart\n                    tasks={hierarchicalTasks}\n                    height={440}\n                    columns={[\n                        { field: 'name', headerText: 'Task', width: 200 },\n                        { field: 'assignee', headerText: 'Owner', width: 90, align: 'center' },\n                    ]}\n                />\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock\n                    code={`const tasks: GanttTask[] = [\n  {\n    id: 'phase-1',\n    name: 'Phase 1 — Discovery',\n    type: 'group',\n    start: new Date('2025-01-01'),\n    end: new Date('2025-01-14'),\n    progress: 90,\n    children: [\n      { id: 'p1-t1', name: 'Stakeholder Interviews', start: '2025-01-01', end: '2025-01-05', progress: 100 },\n      { id: 'p1-t2', name: 'Market Research',        start: '2025-01-03', end: '2025-01-10', progress: 80 },\n    ],\n  },\n  {\n    id: 'milestone-1',\n    name: 'Design Review',\n    type: 'milestone',\n    start: new Date('2025-01-14'),\n    end: new Date('2025-01-14'),\n    color: '#f59e0b',\n  },\n];\n\n<GanttChart tasks={tasks} height={400} />`}\n                />\n            </div>\n        </>\n    );\n};\n\nexport default HierarchicalTasks;\n"
        },
        {
          "title": "QuarterlyView",
          "code": "import cn from 'classnames';\nimport React from 'react';\nimport { GanttChart } from '../../../components/gantt-chart';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\nimport { quarterlyTasks } from './gantt-chart-story-data';\n\nconst QuarterlyView: React.FC = () => {\n    const { isDark } = useStoryTheme();\n\n    return (\n        <>\n            <p className={cn('mb-4 text-sm', { 'text-gray-400': isDark, 'text-gray-500': !isDark })}>\n                Use <code>viewMode=\"quarter\"</code> or <code>\"year\"</code> for roadmap-level planning across many months.\n            </p>\n            <ComponentDemo title=\"Quarterly Roadmap\" centered={false}>\n                <GanttChart\n                    tasks={quarterlyTasks}\n                    viewMode=\"month\"\n                    height={380}\n                    columns={[{ field: 'name', headerText: 'Initiative', width: 200 }]}\n                />\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock\n                    code={`<GanttChart\n  tasks={roadmapTasks}\n  viewMode=\"month\"    // or \"quarter\" | \"year\" for wider ranges\n  height={400}\n  columns={[{ field: 'name', headerText: 'Initiative', width: 200 }]}\n/>`}\n                />\n            </div>\n        </>\n    );\n};\n\nexport default QuarterlyView;\n"
        },
        {
          "title": "ReadOnly",
          "code": "import cn from 'classnames';\nimport React from 'react';\nimport { GanttChart } from '../../../components/gantt-chart';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\nimport { basicTasks, markers } from './gantt-chart-story-data';\n\nconst ReadOnly: React.FC = () => {\n    const { isDark } = useStoryTheme();\n\n    return (\n        <>\n            <p className={cn('mb-4 text-sm', { 'text-gray-400': isDark, 'text-gray-500': !isDark })}>\n                Set <code>readOnly</code> to disable all interactions. Useful for dashboards and reports.\n            </p>\n            <ComponentDemo title=\"Read-Only Gantt\" centered={false}>\n                <GanttChart\n                    tasks={basicTasks}\n                    height={300}\n                    readOnly={true}\n                    markers={markers}\n                />\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock\n                    code={`<GanttChart\n  tasks={tasks}\n  height={400}\n  readOnly={true}\n/>`}\n                />\n            </div>\n        </>\n    );\n};\n\nexport default ReadOnly;\n"
        },
        {
          "title": "SprintPlanning",
          "code": "import cn from 'classnames';\nimport React from 'react';\nimport { GanttChart } from '../../../components/gantt-chart';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\nimport { d, resourceTasks, resourceColumns } from './gantt-chart-story-data';\n\nconst isWeekend = (date: Date) => date.getDay() === 0 || date.getDay() === 6;\n\nconst SprintPlanning: React.FC = () => {\n    const { isDark } = useStoryTheme();\n\n    return (\n        <>\n            <p className={cn('mb-4 text-sm', { 'text-gray-400': isDark, 'text-gray-500': !isDark })}>\n                Use extra <code>data</code> fields with column templates to show metadata like priority or task type alongside the timeline.\n            </p>\n            <ComponentDemo title=\"Sprint Backlog View\" centered={false}>\n                <GanttChart\n                    tasks={resourceTasks}\n                    height={420}\n                    columns={resourceColumns}\n                    fieldsPanelWidth={360}\n                    markers={[\n                        { id: 'sprint-start', date: d(-7), label: 'Sprint Start', color: '#3b82f6' },\n                        { id: 'sprint-end', date: d(11), label: 'Sprint End', color: '#f59e0b' },\n                    ]}\n                    isHoliday={isWeekend}\n                />\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock\n                    code={`const tasks: GanttTask[] = [\n  {\n    id: 'feature-auth',\n    name: 'Feature: Auth',\n    start: '2025-01-06',\n    end: '2025-01-14',\n    progress: 75,\n    assignee: 'Alice',\n    data: { priority: 'High', type: 'Dev' },\n  },\n  // ...\n];\n\nconst columns: GanttColumn[] = [\n  { field: 'name', headerText: 'Task', width: 180 },\n  { field: 'assignee', headerText: 'Assignee', width: 80, align: 'center' },\n  {\n    field: 'data.priority',\n    headerText: 'Priority',\n    width: 75,\n    align: 'center',\n    template: ({ task }) => {\n      const priority = (task.data as any)?.priority;\n      const colors = { Critical: '#ef4444', High: '#f59e0b', Medium: '#3b82f6' };\n      return (\n        <span style={{\n          padding: '1px 6px', borderRadius: 10, fontSize: 10, fontWeight: 600,\n          background: \\`\\${colors[priority]}20\\`, color: colors[priority],\n        }}>\n          {priority}\n        </span>\n      );\n    },\n  },\n];\n\n// Mark weekends as holidays\nconst isHoliday = (date: Date) => date.getDay() === 0 || date.getDay() === 6;\n\n<GanttChart\n  tasks={tasks}\n  columns={columns}\n  fieldsPanelWidth={360}\n  isHoliday={isHoliday}\n  markers={[\n    { date: sprintStart, label: 'Sprint Start', color: '#3b82f6' },\n    { date: sprintEnd,   label: 'Sprint End',   color: '#f59e0b' },\n  ]}\n  height={420}\n/>`}\n                />\n            </div>\n        </>\n    );\n};\n\nexport default SprintPlanning;\n"
        },
        {
          "title": "TaskCreation",
          "code": "import cn from 'classnames';\nimport React, { useState } from 'react';\nimport { GanttChart } from '../../../components/gantt-chart';\nimport type { GanttTask, GanttTaskCreateEvent } from '../../../components/gantt-chart';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\nimport { d } from './gantt-chart-story-data';\n\nconst TaskCreation: React.FC = () => {\n    const { isDark } = useStoryTheme();\n    const [createableTasks, setCreateableTasks] = useState<GanttTask[]>([\n        { id: 'c1', name: 'Existing Task', start: d(-3), end: d(3), progress: 50 },\n    ]);\n    const [lastEvent, setLastEvent] = useState<string>('');\n\n    const handleTaskCreate = (e: GanttTaskCreateEvent) => {\n        const newTask: GanttTask = {\n            id: `new-${Date.now()}`,\n            name: 'New Task',\n            start: e.start,\n            end: e.end,\n            progress: 0,\n            color: '#8b5cf6',\n        };\n        setCreateableTasks(prev => {\n            const next = [...prev];\n            const insertAt = Math.min(Math.max(e.rowIndex, 0), next.length);\n            next.splice(insertAt, 0, newTask);\n            return next;\n        });\n        setLastEvent(`Created task at row ${e.rowIndex + 1}: ${e.start.toLocaleDateString()} – ${e.end.toLocaleDateString()}`);\n    };\n\n    return (\n        <>\n            <p className={cn('mb-4 text-sm', { 'text-gray-400': isDark, 'text-gray-500': !isDark })}>\n                Enable <code>allowTaskCreate</code> and let users draw new tasks by clicking and dragging on empty row space.\n            </p>\n            <ComponentDemo title=\"Draw New Tasks (drag on empty area)\" centered={false}>\n                <div className=\"space-y-3\">\n                    <GanttChart\n                        tasks={createableTasks}\n                        height={300}\n                        allowTaskCreate={true}\n                        onTaskCreate={handleTaskCreate}\n                        onTaskChange={(e) =>\n                            setCreateableTasks(prev =>\n                                prev.map(t => t.id === e.task.id ? { ...t, start: e.start, end: e.end } : t)\n                            )\n                        }\n                    />\n                    {lastEvent.startsWith('Created') && (\n                        <div className={cn('text-sm px-4 py-2 rounded border', {\n                            'border-green-800 bg-green-900/30 text-green-300': isDark,\n                            'border-green-200 bg-green-50 text-green-800': !isDark,\n                        })}>\n                            {lastEvent}\n                        </div>\n                    )}\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock\n                    code={`const [tasks, setTasks] = useState<GanttTask[]>(initialTasks);\n\nconst handleTaskCreate = (e: GanttTaskCreateEvent) => {\n  const newTask: GanttTask = {\n    id: \\`task-\\${Date.now()}\\`,\n    name: 'New Task',\n    start: e.start,\n    end: e.end,\n    progress: 0,\n  };\n  setTasks(prev => [...prev, newTask]);\n};\n\n<GanttChart\n  tasks={tasks}\n  height={400}\n  allowTaskCreate={true}\n  onTaskCreate={handleTaskCreate}\n/>`}\n                />\n            </div>\n        </>\n    );\n};\n\nexport default TaskCreation;\n"
        },
        {
          "title": "TimelineOnly",
          "code": "import cn from 'classnames';\nimport React from 'react';\nimport { GanttChart } from '../../../components/gantt-chart';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\nimport { basicTasks, d } from './gantt-chart-story-data';\n\nconst TimelineOnly: React.FC = () => {\n    const { isDark } = useStoryTheme();\n\n    return (\n        <>\n            <p className={cn('mb-4 text-sm', { 'text-gray-400': isDark, 'text-gray-500': !isDark })}>\n                Hide the left fields panel entirely with <code>showFieldsPanel=&#123;false&#125;</code> for a compact timeline.\n            </p>\n            <ComponentDemo title=\"No Fields Panel\" centered={false}>\n                <GanttChart\n                    tasks={basicTasks}\n                    height={280}\n                    showFieldsPanel={false}\n                    markers={[{ id: 't', date: d(0), label: 'Today', color: '#3b82f6' }]}\n                />\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock\n                    code={`<GanttChart\n  tasks={tasks}\n  height={300}\n  showFieldsPanel={false}\n/>`}\n                />\n            </div>\n        </>\n    );\n};\n\nexport default TimelineOnly;\n"
        },
        {
          "title": "ViewModes",
          "code": "import cn from 'classnames';\nimport React, { useState } from 'react';\nimport { GanttChart } from '../../../components/gantt-chart';\nimport type { GanttViewMode } from '../../../components/gantt-chart';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\nimport { basicTasks } from './gantt-chart-story-data';\n\nconst ViewModes: React.FC = () => {\n    const { isDark } = useStoryTheme();\n    const [viewMode, setViewMode] = useState<GanttViewMode>('day');\n\n    return (\n        <>\n            <p className={cn('mb-4 text-sm', { 'text-gray-400': isDark, 'text-gray-500': !isDark })}>\n                Switch between Day, Week, Month, Quarter, and Year views. Can be controlled externally or left to the built-in toolbar.\n            </p>\n            <ComponentDemo title=\"Controlled View Mode\" centered={false}>\n                <GanttChart\n                    tasks={basicTasks}\n                    height={320}\n                    viewMode={viewMode}\n                    onViewModeChange={setViewMode}\n                />\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock\n                    code={`const [viewMode, setViewMode] = useState<GanttViewMode>('day');\n\n<GanttChart\n  tasks={tasks}\n  height={400}\n  viewMode={viewMode}\n  onViewModeChange={setViewMode}\n/>`}\n                />\n            </div>\n        </>\n    );\n};\n\nexport default ViewModes;\n"
        }
      ],
      "props": {
        "ganttProps": {
          "tasks": {
            "type": "GanttTask[]",
            "required": true,
            "description": "Array of task objects to display on the chart"
          },
          "columns": {
            "type": "GanttColumn[]",
            "default": "[{ field: 'name', headerText: 'Task Name', width: 200 }]",
            "description": "Column definitions for the left fields panel"
          },
          "viewMode": {
            "type": "'day' | 'week' | 'month' | 'quarter' | 'year'",
            "default": "'day'",
            "description": "Controls how the timeline is rendered and grouped"
          },
          "startDate": {
            "type": "Date | string",
            "description": "Override the auto-computed start date of the visible range"
          },
          "endDate": {
            "type": "Date | string",
            "description": "Override the auto-computed end date of the visible range"
          },
          "height": {
            "type": "number | string",
            "default": "500",
            "description": "Total height of the Gantt chart container"
          },
          "rowHeight": {
            "type": "number",
            "default": "40",
            "description": "Height of each task row in pixels"
          },
          "columnWidth": {
            "type": "number",
            "description": "Width of each timeline column. Defaults vary by view mode"
          },
          "fieldsPanelWidth": {
            "type": "number | string",
            "default": "300",
            "description": "Width of the left-side fields/columns panel"
          },
          "showFieldsPanel": {
            "type": "boolean",
            "default": "true",
            "description": "Toggle the left fields panel visibility"
          },
          "showToday": {
            "type": "boolean",
            "default": "true",
            "description": "Highlight today with a vertical line and scroll to it on mount"
          },
          "showDependencies": {
            "type": "boolean",
            "default": "true",
            "description": "Render SVG dependency arrows between tasks"
          },
          "showProgress": {
            "type": "boolean",
            "default": "true",
            "description": "Render the progress overlay on task bars"
          },
          "showTooltip": {
            "type": "boolean",
            "default": "true",
            "description": "Show hover tooltip with task details"
          },
          "markers": {
            "type": "GanttMarker[]",
            "default": "[]",
            "description": "Vertical date markers (deadlines, milestones, events)"
          },
          "isHoliday": {
            "type": "(date: Date) => boolean",
            "description": "Callback to determine if a date should be marked as a holiday"
          },
          "allowTaskDrag": {
            "type": "boolean",
            "default": "true",
            "description": "Allow users to drag tasks to new dates"
          },
          "allowTaskResize": {
            "type": "boolean",
            "default": "true",
            "description": "Allow users to resize task bars from either end"
          },
          "allowTaskCreate": {
            "type": "boolean",
            "default": "false",
            "description": "Allow users to drag on empty rows to create new tasks"
          },
          "readOnly": {
            "type": "boolean",
            "default": "false",
            "description": "Disable all drag, resize, and create interactions"
          },
          "taskBarTemplate": {
            "type": "(props: TaskBarTemplateProps) => JSX.Element",
            "description": "Custom render function for task bar content"
          },
          "tooltipTemplate": {
            "type": "(task: GanttTask) => ReactNode",
            "description": "Custom render function for the hover tooltip"
          },
          "onTaskChange": {
            "type": "(event: GanttTaskChangeEvent) => void",
            "description": "Fires when a task is moved or resized"
          },
          "onTaskClick": {
            "type": "(event: GanttTaskClickEvent) => void",
            "description": "Fires when a task bar is clicked"
          },
          "onTaskDoubleClick": {
            "type": "(event: GanttTaskClickEvent) => void",
            "description": "Fires when a task bar is double-clicked"
          },
          "onTaskCreate": {
            "type": "(event: GanttTaskCreateEvent) => void",
            "description": "Fires when a new task range is drawn (requires allowTaskCreate)"
          },
          "onViewModeChange": {
            "type": "(mode: GanttViewMode) => void",
            "description": "Fires when the user switches the view mode"
          },
          "onExpandToggle": {
            "type": "(task: GanttTask, expanded: boolean) => void",
            "description": "Fires when a group task is expanded or collapsed"
          }
        },
        "taskProps": {
          "id": {
            "type": "string",
            "required": true,
            "description": "Unique identifier for the task"
          },
          "name": {
            "type": "string",
            "required": true,
            "description": "Display name of the task"
          },
          "start": {
            "type": "Date | string",
            "required": true,
            "description": "Start date of the task"
          },
          "end": {
            "type": "Date | string",
            "required": true,
            "description": "End date of the task"
          },
          "progress": {
            "type": "number",
            "default": "0",
            "description": "Completion percentage (0-100)"
          },
          "type": {
            "type": "'task' | 'milestone' | 'group'",
            "default": "'task'",
            "description": "Determines visual style and behavior"
          },
          "color": {
            "type": "string",
            "description": "Custom background color for the task bar"
          },
          "textColor": {
            "type": "string",
            "description": "Custom text color inside the task bar"
          },
          "dependencies": {
            "type": "GanttDependency[]",
            "description": "Array of dependency connections to other tasks"
          },
          "children": {
            "type": "GanttTask[]",
            "description": "Nested child tasks (makes this task a group/parent)"
          },
          "collapsed": {
            "type": "boolean",
            "default": "false",
            "description": "Whether this group is initially collapsed"
          },
          "assignee": {
            "type": "string",
            "description": "Assignee name shown in tooltip and custom columns"
          },
          "draggable": {
            "type": "boolean",
            "default": "true",
            "description": "Override draggability for this specific task"
          },
          "resizable": {
            "type": "boolean",
            "default": "true",
            "description": "Override resizability for this specific task"
          },
          "tooltip": {
            "type": "ReactNode | ((task: GanttTask) => ReactNode)",
            "description": "Custom tooltip content for this task"
          },
          "data": {
            "type": "Record<string, unknown>",
            "description": "Arbitrary extra data accessible in templates"
          }
        }
      },
      "storyDir": "gantt-chart"
    },
    "HtmlEditor": {
      "name": "HtmlEditor",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React, { useState } from 'react';\nimport { HtmlEditor } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst initial = `<h1>HTML Rich Text Editor</h1>\n<p>A <strong>WYSIWYG</strong> editor with the <em>full range</em> of rich formatting: <u>underline</u>, <s>strikethrough</s>, <code>inline code</code>, <mark>highlighted text</mark>, <sup>superscript</sup>, <sub>subscript</sub>.</p>\n<h2>Text colors &amp; fonts</h2>\n<p>You can change <span style=\"color: #3b82f6;\">text color</span>, <span style=\"background-color: #fef3c7;\">background color</span>, <span style=\"font-size: 22px;\">font size</span>, and <span style=\"font-family: Georgia, serif;\">font family</span> on any selection.</p>\n<h2>Lists</h2>\n<ul>\n  <li>Nested unordered lists</li>\n  <li>Items with <strong>inline formatting</strong>\n    <ul>\n      <li>Even deeper</li>\n      <li>Multiple levels supported</li>\n    </ul>\n  </li>\n</ul>\n<ol>\n  <li>Ordered</li>\n  <li>Numbered</li>\n  <li>Sequences</li>\n</ol>\n<ul data-task-list=\"true\" class=\"eui-html-task-list\">\n  <li data-task-item=\"true\"><input type=\"checkbox\" checked=\"checked\" /> Task lists with checkboxes</li>\n  <li data-task-item=\"true\"><input type=\"checkbox\" /> Click the box to toggle</li>\n</ul>\n<h2>Alignment</h2>\n<p style=\"text-align: left;\">Left aligned paragraph.</p>\n<p style=\"text-align: center;\">Center aligned paragraph.</p>\n<p style=\"text-align: right;\">Right aligned paragraph.</p>\n<p style=\"text-align: justify;\">Justified paragraph that stretches across the full width when there is enough content to demonstrate the justification behavior of text blocks.</p>\n<h2>Blockquote</h2>\n<blockquote><p>\"WYSIWYG means what you see is what you get.\" — every rich text editor ever.</p></blockquote>\n<h2>Code block</h2>\n<pre><code>const editor = new HtmlEditor();\neditor.mount('#root');</code></pre>\n<h2>Table</h2>\n<table class=\"eui-html-table\">\n  <thead><tr><th>Feature</th><th>Inline</th><th>Block</th></tr></thead>\n  <tbody>\n    <tr><td>Headings</td><td>—</td><td>yes</td></tr>\n    <tr><td>Colors</td><td>yes</td><td>yes</td></tr>\n    <tr><td>Tables</td><td>—</td><td>yes</td></tr>\n  </tbody>\n</table>\n<hr/>\n<p>Try any of the toolbar actions or keyboard shortcuts — <kbd>Ctrl+B</kbd>, <kbd>Ctrl+I</kbd>, <kbd>Ctrl+U</kbd>, <kbd>Ctrl+K</kbd>, <kbd>Ctrl+Alt+1..6</kbd>.</p>`;\n\nconst code = `import { HtmlEditor } from 'fluxo-ui';\n\nconst [value, setValue] = useState('<h1>Hello</h1>');\n\n<HtmlEditor\n  value={value}\n  onChange={setValue}\n  defaultView=\"split\"\n  maxHeight={520}\n/>`;\n\nconst BasicUsage: React.FC = () => {\n    const [value, setValue] = useState(initial);\n    return (\n        <>\n            <ComponentDemo title=\"Rich Text Editor\" description=\"Full WYSIWYG editing with inline, block, color, font, alignment, list, table, and link/image support.\">\n                <HtmlEditor value={value} onChange={setValue} defaultView=\"split\" maxHeight={560} />\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "CustomToolbar",
          "code": "import React, { useState } from 'react';\nimport { HtmlEditor, MINIMAL_HTML_TOOLBAR, type HtmlToolbarItem } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst customToolbar: HtmlToolbarItem[] = [\n    'bold',\n    'italic',\n    'underline',\n    'divider',\n    'h2',\n    'h3',\n    'divider',\n    'textColor',\n    'bgColor',\n    'divider',\n    'link',\n    'quote',\n];\n\nconst initial = `<h1>Custom Toolbars</h1>\n<p>Configure exactly which formatting buttons appear. Pass <code>toolbar</code> with any subset of actions, or use the built-in <code>MINIMAL_HTML_TOOLBAR</code>.</p>\n<ul>\n    <li><strong>bold</strong>, <em>italic</em>, <u>underline</u>, <s>strike</s></li>\n    <li><a href=\"https://fluxo-ui.utilsware.com/\">Link to docs</a></li>\n</ul>\n<blockquote><p>Quotes still work even when the toolbar is hidden — all keyboard shortcuts are always available.</p></blockquote>`;\n\nconst code = `import { HtmlEditor, MINIMAL_HTML_TOOLBAR } from 'fluxo-ui';\n\n<HtmlEditor toolbar={MINIMAL_HTML_TOOLBAR} />\n\n<HtmlEditor\n  toolbar={['bold', 'italic', 'underline', 'divider', 'h2', 'h3', 'divider', 'textColor', 'link', 'quote']}\n/>\n\n<HtmlEditor toolbar={false} />`;\n\nconst CustomToolbar: React.FC = () => {\n    const [a, setA] = useState(initial);\n    const [b, setB] = useState(initial);\n    const [c, setC] = useState(initial);\n    return (\n        <>\n            <ComponentDemo title=\"Minimal Toolbar\" description=\"Use the built-in minimal preset for simple comment boxes.\">\n                <HtmlEditor value={a} onChange={setA} toolbar={MINIMAL_HTML_TOOLBAR} maxHeight={320} />\n            </ComponentDemo>\n            <div className=\"mt-6\">\n                <ComponentDemo title=\"Custom Selection\" description=\"Pass an explicit list of toolbar actions in your preferred order.\">\n                    <HtmlEditor value={b} onChange={setB} toolbar={customToolbar} maxHeight={320} />\n                </ComponentDemo>\n            </div>\n            <div className=\"mt-6\">\n                <ComponentDemo title=\"No Toolbar\" description=\"Disable the toolbar entirely — keyboard shortcuts still work.\">\n                    <HtmlEditor value={c} onChange={setC} toolbar={false} maxHeight={320} />\n                </ComponentDemo>\n            </div>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default CustomToolbar;\n"
        },
        {
          "title": "ImageUploadDeferred",
          "code": "import React, { useCallback, useRef, useState } from 'react';\nimport { Button, HtmlEditor, type HtmlEditorHandle } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst initial = `<h1>Deferred Upload (Flush on Submit)</h1>\n<p>Drop or paste images — they appear instantly via local <code>blob:</code> URLs. When you click <strong>Submit</strong>, the editor flushes all pending uploads via <code>flushUploads()</code> and replaces the blob URLs with the real ones.</p>\n<h2>Workflow</h2>\n<ol>\n    <li>Drop or paste any <strong>image</strong> into the editor</li>\n    <li>Keep editing — images show up immediately</li>\n    <li>Click <strong>Submit</strong> to run all uploads and get the final HTML</li>\n</ol>\n<p><img src=\"https://images.unsplash.com/photo-1472214103451-9374bd1c798e?w=800\" alt=\"Pre-uploaded image\" /></p>\n<blockquote><p>Use this strategy when you don't want to upload until the user actually commits their content.</p></blockquote>`;\n\nconst code = `const editorRef = useRef<HtmlEditorHandle>(null);\n\n<HtmlEditor\n  ref={editorRef}\n  value={value}\n  onChange={setValue}\n  uploadStrategy=\"deferred\"\n  uploadImage={async (file) => await myUploader(file)}\n/>\n\n<Button\n  onClick={async () => {\n    const finalHtml = await editorRef.current?.flushUploads();\n    submitForm(finalHtml);\n  }}\n>\n  Submit\n</Button>`;\n\nconst fakeUpload = async (file: File): Promise<string> => {\n    await new Promise((r) => setTimeout(r, 800));\n    return 'https://cdn.utilsware.com/uploads/' + encodeURIComponent(file.name);\n};\n\nconst ImageUploadDeferred: React.FC = () => {\n    const [value, setValue] = useState(initial);\n    const [submitted, setSubmitted] = useState<string | null>(null);\n    const [busy, setBusy] = useState(false);\n    const editorRef = useRef<HtmlEditorHandle>(null);\n\n    const handleSubmit = useCallback(async () => {\n        if (!editorRef.current) return;\n        setBusy(true);\n        try {\n            const final = await editorRef.current.flushUploads();\n            setSubmitted(final);\n        } finally {\n            setBusy(false);\n        }\n    }, []);\n\n    return (\n        <>\n            <ComponentDemo title=\"Deferred Upload Strategy\" description=\"Images are inserted as blob URLs immediately for instant preview, then uploaded only when you flush.\">\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16 }}>\n                    <HtmlEditor\n                        ref={editorRef}\n                        value={value}\n                        onChange={setValue}\n                        uploadStrategy=\"deferred\"\n                        uploadImage={fakeUpload}\n                        maxImageSize={5 * 1024 * 1024}\n                        maxHeight={460}\n                    />\n                    <div\n                        style={{\n                            padding: '12px 16px',\n                            background: 'var(--eui-bg-subtle)',\n                            border: '1px solid var(--eui-border-subtle)',\n                            borderRadius: 6,\n                        }}\n                    >\n                        <Button onClick={handleSubmit} disabled={busy}>\n                            {busy ? 'Uploading...' : 'Submit'}\n                        </Button>\n                    </div>\n                    {submitted && (\n                        <pre\n                            style={{\n                                margin: 0,\n                                padding: 14,\n                                background: 'var(--eui-bg-subtle)',\n                                border: '1px solid var(--eui-border-subtle)',\n                                borderRadius: 6,\n                                fontSize: 12,\n                                color: 'var(--eui-text)',\n                                whiteSpace: 'pre-wrap',\n                                overflow: 'auto',\n                                maxHeight: 240,\n                            }}\n                        >\n                            {submitted}\n                        </pre>\n                    )}\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default ImageUploadDeferred;\n"
        },
        {
          "title": "ImageUploadImmediate",
          "code": "import React, { useCallback, useState } from 'react';\nimport { HtmlEditor } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst initial = `<h1>Immediate Upload</h1>\n<p>Click the <strong>image</strong> button in the toolbar, or <em>paste / drop</em> an image directly into the editor.</p>\n<p>The editor calls your <code>uploadImage</code> callback immediately and inserts the final URL once it resolves.</p>\n<h2>Things to try</h2>\n<ol>\n    <li>Click the image toolbar button and choose <strong>Upload</strong></li>\n    <li>Paste an image from your clipboard</li>\n    <li>Drag an image file from your desktop onto the editor</li>\n</ol>\n<p><img src=\"https://images.unsplash.com/photo-1469474968028-56623f02e42e?w=800\" alt=\"A valley at dawn\" /></p>\n<blockquote><p>Already-hosted images work too — paste the URL via the <strong>From URL</strong> tab in the image dialog.</p></blockquote>`;\n\nconst code = `<HtmlEditor\n  value={value}\n  onChange={setValue}\n  uploadStrategy=\"immediate\"\n  uploadImage={async (file) => {\n    const url = await myUploader(file);\n    return url;\n  }}\n  maxImageSize={5 * 1024 * 1024}\n  acceptedImageTypes={['image/png', 'image/jpeg', 'image/webp']}\n/>`;\n\nconst fakeUpload = async (file: File): Promise<string> => {\n    await new Promise((r) => setTimeout(r, 800));\n    return URL.createObjectURL(file);\n};\n\nconst ImageUploadImmediate: React.FC = () => {\n    const [value, setValue] = useState(initial);\n    const [log, setLog] = useState<string[]>([]);\n\n    const handleUpload = useCallback(async (file: File) => {\n        setLog((prev) => [...prev, 'Uploading ' + file.name + ' (' + (file.size / 1024).toFixed(0) + ' KB)']);\n        const url = await fakeUpload(file);\n        setLog((prev) => [...prev, 'Uploaded ' + file.name]);\n        return url;\n    }, []);\n\n    return (\n        <>\n            <ComponentDemo title=\"Immediate Upload Strategy\" description=\"Every selected image uploads right away and the final URL is inserted into the HTML.\">\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16 }}>\n                    <HtmlEditor\n                        value={value}\n                        onChange={setValue}\n                        uploadStrategy=\"immediate\"\n                        uploadImage={handleUpload}\n                        maxImageSize={5 * 1024 * 1024}\n                        acceptedImageTypes={['image/png', 'image/jpeg', 'image/webp', 'image/gif']}\n                        onUploadError={(msg) => setLog((prev) => [...prev, 'Error: ' + msg])}\n                        maxHeight={480}\n                    />\n                    {log.length > 0 && (\n                        <div\n                            style={{\n                                padding: 14,\n                                background: 'var(--eui-bg-subtle)',\n                                border: '1px solid var(--eui-border-subtle)',\n                                borderRadius: 6,\n                                fontFamily: 'ui-monospace, monospace',\n                                fontSize: 12,\n                                color: 'var(--eui-text-muted)',\n                            }}\n                        >\n                            {log.slice(-6).map((l, i) => (\n                                <div key={i}>{l}</div>\n                            ))}\n                        </div>\n                    )}\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default ImageUploadImmediate;\n"
        },
        {
          "title": "PreviewOnly",
          "code": "import React from 'react';\nimport { HtmlPreview } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst sample = `<h1>Preview-only Renderer</h1>\n<p>Use <strong>HtmlPreview</strong> when you only need to <em>render</em> sanitized HTML — comments, blog posts, or read-only docs.</p>\n<h2>What this renderer supports</h2>\n<p>Inline: <strong>bold</strong>, <em>italic</em>, <u>underline</u>, <s>strike</s>, <code>code</code>, <mark>highlight</mark>, <sup>sup</sup>, <sub>sub</sub>, and <a href=\"https://fluxo-ui.utilsware.com/\">links</a>.</p>\n<p>Colors: <span style=\"color: #3b82f6;\">blue</span>, <span style=\"color: #ef4444;\">red</span>, <span style=\"background-color: #fef3c7;\">highlighted</span>.</p>\n<h3>Lists</h3>\n<ol>\n    <li>First top-level item</li>\n    <li>Second with nested list\n        <ul>\n            <li>Nested bullet</li>\n            <li>Another nested bullet</li>\n        </ul>\n    </li>\n</ol>\n<h3>Blockquote</h3>\n<blockquote><p>Blockquotes can span multiple lines and contain <strong>inline formatting</strong>.</p></blockquote>\n<h3>Code block</h3>\n<pre><code>import { HtmlPreview } from 'fluxo-ui';\n&lt;HtmlPreview value={html} /&gt;</code></pre>\n<h3>Table</h3>\n<table>\n    <thead><tr><th>Left</th><th>Center</th><th>Right</th></tr></thead>\n    <tbody>\n        <tr><td>one</td><td>two</td><td>three</td></tr>\n        <tr><td>short</td><td>long</td><td>text</td></tr>\n    </tbody>\n</table>\n<hr/>\n<p>Dangerous scripts and <code>javascript:</code> URLs are automatically stripped.</p>`;\n\nconst unsafeSample = `<p>Safe paragraph</p><script>alert('xss')</script><p><a href=\"javascript:alert(1)\">click</a></p><p onclick=\"alert(1)\">event handler attempt</p>`;\n\nconst code = `import { HtmlPreview } from 'fluxo-ui';\n\n<HtmlPreview value={html} openLinksInNewTab />`;\n\nconst PreviewOnly: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo title=\"Preview Only\" description=\"Render sanitized HTML without the editor — ideal for displaying user-generated content.\">\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16 }}>\n                    <div style={{ border: '1px solid var(--eui-border-subtle)', borderRadius: 6, background: 'var(--eui-bg)' }}>\n                        <HtmlPreview value={sample} />\n                    </div>\n                    <div\n                        style={{\n                            padding: '12px 16px',\n                            background: 'var(--eui-bg-subtle)',\n                            border: '1px solid var(--eui-border-subtle)',\n                            borderRadius: 6,\n                            fontSize: 12,\n                            color: 'var(--eui-text-muted)',\n                        }}\n                    >\n                        Input: <code>{unsafeSample.replace(/</g, '&lt;')}</code>\n                        <div style={{ marginTop: 8, padding: 10, background: 'var(--eui-bg)', borderRadius: 4, border: '1px solid var(--eui-border-subtle)' }}>\n                            <HtmlPreview value={unsafeSample} />\n                        </div>\n                        <div style={{ marginTop: 6 }}>Scripts and unsafe URLs were removed automatically.</div>\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default PreviewOnly;\n"
        },
        {
          "title": "ReadOnly",
          "code": "import React from 'react';\nimport { HtmlEditor } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst sample = `<h1>Read-only Mode</h1>\n<p>The editor can be rendered in <strong>read-only</strong> mode — content remains selectable, but the toolbar is disabled.</p>\n<h2>What you can see</h2>\n<p>Inline formatting still renders: <strong>bold</strong>, <em>italic</em>, <u>underline</u>, <s>strike</s>, <code>inline code</code>, and <a href=\"https://fluxo-ui.utilsware.com/\">links</a>.</p>\n<ul>\n    <li>Useful for displaying the editor with its chrome intact</li>\n    <li>Prevents any formatting changes</li>\n    <li>Still allows copy to clipboard</li>\n</ul>\n<blockquote><p>Read-only doesn't mean \"hidden\". It means \"visible but immutable.\"</p></blockquote>`;\n\nconst code = `<HtmlEditor value={value} readOnly defaultView=\"split\" />`;\n\nconst ReadOnly: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Read-only Editor\" description=\"All toolbar actions and keyboard shortcuts are disabled.\">\n            <HtmlEditor value={sample} readOnly defaultView=\"split\" maxHeight={420} />\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default ReadOnly;\n"
        },
        {
          "title": "ViewModes",
          "code": "import React, { useState } from 'react';\nimport { HtmlEditor, type EditorViewMode } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst initial = `<h1>View Modes</h1>\n<p>Switch between <strong>Edit</strong>, <em>Split</em>, and <strong>Preview</strong> from the top-right toolbar.</p>\n<h2>Sample content</h2>\n<p>Inline: <strong>bold</strong>, <em>italic</em>, <s>strike</s>, <code>inline code</code>, and a <a href=\"https://fluxo-ui.utilsware.com/\">link</a>.</p>\n<ul>\n    <li>Edit-only hides the preview pane</li>\n    <li>Split shows both side-by-side (tabs on mobile)</li>\n    <li>Preview hides the editor entirely</li>\n</ul>\n<blockquote><p>Each view can be controlled externally via the <code>view</code> prop.</p></blockquote>`;\n\nconst code = `const [view, setView] = useState<EditorViewMode>('split');\n\n<HtmlEditor\n  value={value}\n  onChange={setValue}\n  view={view}\n  onViewChange={setView}\n/>`;\n\nconst ViewModes: React.FC = () => {\n    const [value, setValue] = useState(initial);\n    const [view, setView] = useState<EditorViewMode>('split');\n    return (\n        <>\n            <ComponentDemo title=\"Edit / Split / Preview\" description=\"Fully controlled view mode — wire it to your own UI if you want external toggles.\">\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16 }}>\n                    <HtmlEditor value={value} onChange={setValue} view={view} onViewChange={setView} maxHeight={460} />\n                    <div\n                        style={{\n                            padding: '12px 16px',\n                            background: 'var(--eui-bg-subtle)',\n                            border: '1px solid var(--eui-border-subtle)',\n                            borderRadius: 6,\n                            fontSize: 13,\n                            color: 'var(--eui-text-muted)',\n                        }}\n                    >\n                        Current view: <strong style={{ color: 'var(--eui-text)' }}>{view}</strong>\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default ViewModes;\n"
        }
      ],
      "props": {
        "editorProps": {
          "value": {
            "type": "string",
            "description": "Controlled HTML value."
          },
          "defaultValue": {
            "type": "string",
            "description": "Initial value when uncontrolled."
          },
          "onChange": {
            "type": "(value: string) => void",
            "description": "Called whenever the HTML changes."
          },
          "placeholder": {
            "type": "string",
            "default": "'Start writing...'",
            "description": "Placeholder shown when empty."
          },
          "readOnly": {
            "type": "boolean",
            "default": "false",
            "description": "Disable all editing while keeping the chrome."
          },
          "disabled": {
            "type": "boolean",
            "default": "false",
            "description": "Fully disable the editor."
          },
          "minHeight": {
            "type": "string | number",
            "default": "'320px'",
            "description": "Minimum height of the editor body."
          },
          "maxHeight": {
            "type": "string | number",
            "description": "Optional max height (scrolls beyond)."
          },
          "view": {
            "type": "'edit' | 'split' | 'preview'",
            "description": "Controlled view mode."
          },
          "defaultView": {
            "type": "'edit' | 'split' | 'preview'",
            "default": "'edit'",
            "description": "Initial view when uncontrolled."
          },
          "onViewChange": {
            "type": "(view: EditorViewMode) => void",
            "description": "Called when the user toggles views."
          },
          "allowedViews": {
            "type": "EditorViewMode[]",
            "description": "Restrict which view modes appear in the switcher."
          },
          "toolbar": {
            "type": "HtmlToolbarItem[] | false",
            "default": "DEFAULT_HTML_TOOLBAR",
            "description": "Toolbar configuration or false to hide."
          },
          "showToolbar": {
            "type": "boolean",
            "default": "true",
            "description": "Hide the toolbar entirely."
          },
          "showStatusBar": {
            "type": "boolean",
            "default": "true",
            "description": "Show word/char count footer."
          },
          "showWordCount": {
            "type": "boolean",
            "default": "true",
            "description": "Toggle word count in the status bar."
          },
          "uploadImage": {
            "type": "(file: File) => Promise<string>",
            "description": "Async upload callback — must resolve with the final URL."
          },
          "uploadStrategy": {
            "type": "'immediate' | 'deferred'",
            "default": "'immediate'",
            "description": "Upload immediately or defer to flushUploads()."
          },
          "maxImageSize": {
            "type": "number",
            "description": "Maximum file size in bytes."
          },
          "acceptedImageTypes": {
            "type": "string[]",
            "description": "Array of MIME types accepted for upload."
          },
          "onUploadError": {
            "type": "(message: string, file?: File) => void",
            "description": "Called when validation or upload fails."
          },
          "sanitize": {
            "type": "(html: string) => string",
            "description": "Custom sanitizer for paste and preview (defaults to built-in allow-list)."
          },
          "sanitizerConfig": {
            "type": "HtmlSanitizerConfig",
            "description": "Override the allow-list used by the built-in sanitizer."
          },
          "openLinksInNewTab": {
            "type": "boolean",
            "default": "true",
            "description": "Open preview links with target=\"_blank\"."
          },
          "spellCheck": {
            "type": "boolean",
            "default": "true",
            "description": "Enable browser spellcheck on the editable surface."
          },
          "autoFocus": {
            "type": "boolean",
            "default": "false",
            "description": "Focus the editor on mount."
          },
          "ariaLabel": {
            "type": "string",
            "default": "'Rich text editor'",
            "description": "Accessible label for the editor."
          }
        },
        "previewProps": {
          "value": {
            "type": "string",
            "description": "HTML source to render."
          },
          "sanitize": {
            "type": "(html: string) => string",
            "description": "Custom sanitizer — defaults to the built-in allow-list."
          },
          "sanitizerConfig": {
            "type": "HtmlSanitizerConfig",
            "description": "Override the allow-list used by the built-in sanitizer."
          },
          "openLinksInNewTab": {
            "type": "boolean",
            "default": "true",
            "description": "Add target=\"_blank\" rel=\"noopener\" to links."
          },
          "emptyFallback": {
            "type": "React.ReactNode",
            "description": "Shown when value is empty."
          }
        }
      },
      "storyDir": "html-editor"
    },
    "ImageEditor": {
      "name": "ImageEditor",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React, { useState } from 'react';\nimport type { EditorState } from '../../../components';\nimport { ImageEditor } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst sampleImage = 'https://picsum.photos/seed/fluxo/800/600';\n\nconst code = `import { ImageEditor, type EditorState } from 'fluxo-ui';\n\nfunction Editor() {\n  const [editState, setEditState] = useState<EditorState | null>(null);\n\n  const download = () => {\n    if (!editState) return;\n    const a = document.createElement('a');\n    a.href = editState.flattened;\n    a.download = 'edited-image.png';\n    a.click();\n  };\n\n  return (\n    <>\n      <ImageEditor\n        src=\"https://picsum.photos/seed/fluxo/800/600\"\n        alt=\"Sample landscape\"\n        editState={editState}\n        onEditStateChange={setEditState}\n      />\n      <button onClick={download}>Download</button>\n    </>\n  );\n}`;\n\nconst BasicUsage: React.FC = () => {\n    const [editState, setEditState] = useState<EditorState | null>(null);\n\n    const download = () => {\n        if (!editState) return;\n        const a = document.createElement('a');\n        a.href = editState.flattened;\n        a.download = 'edited-image.png';\n        a.click();\n    };\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Full Editor\"\n                description=\"Image editor with all tools enabled. Edits are emitted through onEditStateChange; the consumer decides what to do with the result.\"\n            >\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16 }}>\n                    <div style={{ width: '100%', height: 500 }}>\n                        <ImageEditor\n                            src={sampleImage}\n                            alt=\"Sample landscape\"\n                            editState={editState}\n                            onEditStateChange={setEditState}\n                        />\n                    </div>\n                    <div\n                        style={{\n                            display: 'flex',\n                            gap: 12,\n                            alignItems: 'center',\n                            padding: '12px 16px',\n                            background: 'var(--eui-bg-subtle)',\n                            border: '1px solid var(--eui-border-subtle)',\n                            borderRadius: 6,\n                        }}\n                    >\n                        <button\n                            type=\"button\"\n                            onClick={download}\n                            disabled={!editState}\n                            className=\"eui-image-editor-action-btn\"\n                            style={{ cursor: editState ? 'pointer' : 'not-allowed' }}\n                        >\n                            Download result\n                        </button>\n                        <span style={{ color: 'var(--eui-text-muted)' }}>\n                            Edits captured: <strong>{editState ? 'yes' : 'none'}</strong>\n                        </span>\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "CropOnly",
          "code": "import React, { useState } from 'react';\nimport type { EditorState } from '../../../components';\nimport { ImageEditor } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst sampleImage = 'https://picsum.photos/seed/fluxo/800/600';\n\nconst code = `import { ImageEditor, type EditorState } from 'fluxo-ui';\n\nconst [editState, setEditState] = useState<EditorState | null>(null);\n\n<ImageEditor\n  src=\"https://picsum.photos/seed/fluxo/800/600\"\n  tools={['crop']}\n  defaultTool=\"crop\"\n  cropModes={['custom', 'square', '16:9', '4:3', '1:1']}\n  editState={editState}\n  onEditStateChange={setEditState}\n/>`;\n\nconst CropOnly: React.FC = () => {\n    const [editState, setEditState] = useState<EditorState | null>(null);\n\n    return (\n        <>\n            <ComponentDemo title=\"Crop Only\" description=\"Editor restricted to crop tool with predefined aspect ratios.\">\n                <div className=\"w-full\" style={{ height: 500 }}>\n                    <ImageEditor\n                        src={sampleImage}\n                        alt=\"Crop demo\"\n                        tools={['crop']}\n                        defaultTool=\"crop\"\n                        cropModes={['custom', 'square', '16:9', '4:3', '1:1']}\n                        editState={editState}\n                        onEditStateChange={setEditState}\n                    />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default CropOnly;\n"
        },
        {
          "title": "CustomTools",
          "code": "import React, { useState } from 'react';\nimport type { EditorState } from '../../../components';\nimport { ImageEditor } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst sampleImage = 'https://picsum.photos/seed/fluxo/800/600';\n\nconst code = `import { ImageEditor, type EditorState } from 'fluxo-ui';\n\nconst [editState, setEditState] = useState<EditorState | null>(null);\n\n<ImageEditor\n  src=\"https://picsum.photos/seed/fluxo/800/600\"\n  tools={['crop', 'rotate', 'flip', 'blur']}\n  defaultTool=\"rotate\"\n  maxHistory={20}\n  editState={editState}\n  onEditStateChange={setEditState}\n/>`;\n\nconst CustomTools: React.FC = () => {\n    const [editState, setEditState] = useState<EditorState | null>(null);\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Custom Tool Subset\"\n                description=\"Editor with only crop, rotate, flip, and blur tools. Default tool set to rotate.\"\n            >\n                <div className=\"w-full\" style={{ height: 500 }}>\n                    <ImageEditor\n                        src={sampleImage}\n                        alt=\"Custom tools demo\"\n                        tools={['crop', 'rotate', 'flip', 'blur']}\n                        defaultTool=\"rotate\"\n                        maxHistory={20}\n                        editState={editState}\n                        onEditStateChange={setEditState}\n                    />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default CustomTools;\n"
        },
        {
          "title": "PersistedEdits",
          "code": "import React, { useState } from 'react';\n\nimport type { EditorState } from '../../../components';\nimport { ImageEditor } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst sampleImage = 'https://picsum.photos/seed/fluxo-persist/800/600';\n\nconst code = `import { ImageEditor, type EditorState } from 'fluxo-ui';\n\nfunction Editor() {\n  // Treat editState like a controlled input value: store what onEditStateChange\n  // gives you, then pass it back as editState to reopen with the same edits.\n  const [editState, setEditState] = useState<EditorState | null>(null);\n\n  return (\n    <ImageEditor\n      src=\"https://picsum.photos/seed/fluxo-persist/800/600\"\n      editState={editState}\n      onEditStateChange={setEditState}\n    />\n  );\n}`;\n\nconst PersistedEdits: React.FC = () => {\n    const [editState, setEditState] = useState<EditorState | null>(null);\n    const [mounted, setMounted] = useState(true);\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Persisted Edits\"\n                description=\"Crop and annotate, then close and reopen the editor — the edits return as live, movable layers because the editor state is saved and restored.\"\n            >\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16 }}>\n                    <div style={{ width: '100%', height: 500 }}>\n                        {mounted ? (\n                            <ImageEditor\n                                src={sampleImage}\n                                alt=\"Persisted edits demo\"\n                                editState={editState}\n                                onEditStateChange={setEditState}\n                            />\n                        ) : (\n                            <div\n                                style={{\n                                    width: '100%',\n                                    height: '100%',\n                                    display: 'flex',\n                                    alignItems: 'center',\n                                    justifyContent: 'center',\n                                    border: '1px dashed var(--eui-border-subtle)',\n                                    borderRadius: 6,\n                                    color: 'var(--eui-text-muted)',\n                                }}\n                            >\n                                Editor closed — reopen to restore your edits.\n                            </div>\n                        )}\n                    </div>\n                    <div\n                        style={{\n                            display: 'flex',\n                            flexWrap: 'wrap',\n                            gap: 12,\n                            alignItems: 'center',\n                            padding: '12px 16px',\n                            background: 'var(--eui-bg-subtle)',\n                            border: '1px solid var(--eui-border-subtle)',\n                            borderRadius: 6,\n                        }}\n                    >\n                        <button\n                            type=\"button\"\n                            onClick={() => setMounted((m) => !m)}\n                            style={{ cursor: 'pointer' }}\n                            className=\"eui-image-editor-action-btn\"\n                        >\n                            {mounted ? 'Close editor' : 'Reopen editor'}\n                        </button>\n                        <button\n                            type=\"button\"\n                            onClick={() => setEditState(null)}\n                            style={{ cursor: 'pointer' }}\n                            className=\"eui-image-editor-action-btn\"\n                        >\n                            Clear saved state\n                        </button>\n                        <span style={{ color: 'var(--eui-text-muted)' }}>\n                            Saved edit state: <strong>{editState ? 'present' : 'none'}</strong>\n                        </span>\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default PersistedEdits;\n"
        }
      ],
      "props": {
        "imageEditorProps": {
          "src": {
            "type": "string",
            "required": true,
            "description": "URL of the image to edit."
          },
          "alt": {
            "type": "string",
            "description": "Alt text for the image."
          },
          "width": {
            "type": "number | string",
            "description": "Width of the editor container."
          },
          "height": {
            "type": "number | string",
            "description": "Height of the editor container."
          },
          "tools": {
            "type": "EditorTool[]",
            "default": "['crop', 'rotate', 'flip', 'blur', 'annotate', 'transparency', 'tilt']",
            "description": "Array of tools to enable in the toolbar."
          },
          "defaultTool": {
            "type": "EditorTool",
            "description": "Tool to activate on mount."
          },
          "maxHistory": {
            "type": "number",
            "description": "Maximum number of undo/redo history entries."
          },
          "className": {
            "type": "string",
            "description": "Additional CSS class for the editor container."
          },
          "cropModes": {
            "type": "CropMode[]",
            "default": "['custom', 'square', 'circle', '16:9', '4:3', '3:2', '1:1']",
            "description": "Available crop aspect ratio presets."
          },
          "editState": {
            "type": "EditorState | null",
            "description": "Saved editor state to restore on mount (crop, rotate, flip, blur, annotations, current base image). Pass back the object received from onEditStateChange to reopen with the same edits intact. Leave undefined for an uncontrolled editor that manages its own state."
          },
          "onEditStateChange": {
            "type": "(state: EditorState) => void",
            "description": "Called whenever the edits change, with a serializable snapshot of the full editor state. Persist it and pass it back via editState to restore the session later."
          }
        }
      },
      "storyDir": "image-editor"
    },
    "JsonEditor": {
      "name": "JsonEditor",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "ArrayEditing",
          "code": "import React, { useState } from 'react';\nimport type { JsonValue } from '../../../components';\nimport { JsonEditor } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { arrayData } from './json-editor-story-data';\n\nconst code = `import { JsonEditor } from 'fluxo-ui';\n\nconst data = {\n  fruits: ['Apple', 'Banana', 'Cherry'],\n  users: [\n    { name: 'Alice', role: 'admin' },\n    { name: 'Bob', role: 'user' },\n  ],\n};\n\n<JsonEditor value={data} onChange={setData} expandDepth={2} />`;\n\nconst ArrayEditing: React.FC = () => {\n    const [data, setData] = useState<JsonValue>(arrayData);\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Arrays & Nested Arrays\"\n                description=\"Full array editing with add, remove, and insert operations\"\n                centered={false}\n            >\n                <div className=\"w-full p-4\">\n                    <JsonEditor value={data} onChange={setData} expandDepth={2} />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default ArrayEditing;\n"
        },
        {
          "title": "BasicUsage",
          "code": "import React, { useState } from 'react';\nimport type { JsonValue } from '../../../components';\nimport { JsonEditor } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { basicObject } from './json-editor-story-data';\n\nconst code = `import { JsonEditor } from 'fluxo-ui';\n\nconst [data, setData] = useState({\n  name: 'John Doe',\n  age: 30,\n  email: 'john@example.com',\n  active: true,\n  role: null,\n});\n\n<JsonEditor value={data} onChange={setData} />`;\n\nconst BasicUsage: React.FC = () => {\n    const [data, setData] = useState<JsonValue>(basicObject);\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Basic JSON Editor\"\n                description=\"Edit simple key-value pairs with automatic type detection\"\n                centered={false}\n            >\n                <div className=\"w-full p-4\">\n                    <JsonEditor value={data} onChange={setData} />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "ComplexData",
          "code": "import React, { useState } from 'react';\nimport { JsonEditor } from '../../../components';\nimport type { JsonValue } from '../../../components';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { complexData } from './json-editor-story-data';\n\nconst ComplexData: React.FC = () => {\n    const [data, setData] = useState<JsonValue>(complexData);\n\n    return (\n        <ComponentDemo title=\"Complex Nested Data\" description=\"Real-world configuration with mixed nested objects, arrays, URLs, and null values\" centered={false}>\n            <div className=\"w-full p-4\">\n                <JsonEditor\n                    value={data}\n                    onChange={setData}\n                    expandDepth={2}\n                    showItemCount\n                    maxHeight={400}\n                />\n            </div>\n        </ComponentDemo>\n    );\n};\n\nexport default ComplexData;\n"
        },
        {
          "title": "NestedObjects",
          "code": "import React, { useState } from 'react';\nimport type { JsonValue } from '../../../components';\nimport { JsonEditor } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { nestedObject } from './json-editor-story-data';\n\nconst code = `import { JsonEditor } from 'fluxo-ui';\n\nconst data = {\n  user: {\n    id: 1,\n    profile: { firstName: 'Jane', lastName: 'Smith' },\n    settings: { theme: 'dark', notifications: true },\n  },\n};\n\n<JsonEditor value={data} onChange={setData} expandDepth={2} />`;\n\nconst NestedObjects: React.FC = () => {\n    const [data, setData] = useState<JsonValue>(nestedObject);\n\n    return (\n        <>\n            <ComponentDemo title=\"Nested Objects\" description=\"Deep object hierarchies with collapsible tree view\" centered={false}>\n                <div className=\"w-full p-4\">\n                    <JsonEditor value={data} onChange={setData} expandDepth={2} />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default NestedObjects;\n"
        },
        {
          "title": "PermissionControls",
          "code": "import cn from 'classnames';\nimport React, { useState } from 'react';\nimport { JsonEditor } from '../../../components';\nimport type { JsonValue } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\n\nconst sampleData: JsonValue = {\n    project: 'FluxoUI',\n    version: '1.0.0',\n    settings: {\n        debug: false,\n        maxRetries: 3,\n    },\n    tags: ['react', 'typescript'],\n};\n\nconst code = `<JsonEditor\n  value={data}\n  onChange={setData}\n  allowEditKey={false}\n  allowRemove={false}\n  allowInsert={false}\n/>`;\n\nconst PermissionControls: React.FC = () => {\n    const { isDark } = useStoryTheme();\n    const [data1, setData1] = useState<JsonValue>({ ...sampleData as Record<string, JsonValue> });\n    const [data2, setData2] = useState<JsonValue>({ ...sampleData as Record<string, JsonValue> });\n    const [data3, setData3] = useState<JsonValue>({ ...sampleData as Record<string, JsonValue> });\n\n    return (\n        <>\n            <ComponentDemo title=\"Permission Controls\" description=\"Fine-grained control over edit, add, and remove operations\" centered={false}>\n                <div className=\"w-full space-y-6 p-4\">\n                    <div>\n                        <p className={cn('text-sm mb-2 font-medium', { 'text-gray-400': isDark, 'text-gray-600': !isDark })}>Values only (no key editing, no add/remove)</p>\n                        <JsonEditor\n                            value={data1}\n                            onChange={setData1}\n                            allowEditKey={false}\n                            allowRemove={false}\n                            allowInsert={false}\n                            expandDepth={2}\n                        />\n                    </div>\n                    <div>\n                        <p className={cn('text-sm mb-2 font-medium', { 'text-gray-400': isDark, 'text-gray-600': !isDark })}>No delete allowed</p>\n                        <JsonEditor\n                            value={data2}\n                            onChange={setData2}\n                            allowRemove={false}\n                            expandDepth={2}\n                        />\n                    </div>\n                    <div>\n                        <p className={cn('text-sm mb-2 font-medium', { 'text-gray-400': isDark, 'text-gray-600': !isDark })}>No add allowed</p>\n                        <JsonEditor\n                            value={data3}\n                            onChange={setData3}\n                            allowInsert={false}\n                            expandDepth={2}\n                        />\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default PermissionControls;\n"
        },
        {
          "title": "ReadOnlyMode",
          "code": "import React from 'react';\nimport { JsonEditor } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { readOnlyData } from './json-editor-story-data';\n\nconst code = `import { JsonEditor } from 'fluxo-ui';\n\n<JsonEditor value={data} readOnly />`;\n\nconst ReadOnlyMode: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo title=\"Read-Only Viewer\" description=\"Display JSON data without edit capabilities\" centered={false}>\n                <div className=\"w-full p-4\">\n                    <JsonEditor value={readOnlyData} readOnly expandDepth={2} />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default ReadOnlyMode;\n"
        },
        {
          "title": "SizeVariants",
          "code": "import cn from 'classnames';\nimport React, { useState } from 'react';\nimport { JsonEditor } from '../../../components';\nimport type { JsonEditorSize, JsonValue } from '../../../components';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\n\nconst sampleData: JsonValue = {\n    name: 'Example',\n    count: 42,\n    active: true,\n    tags: ['react', 'typescript'],\n};\n\nconst sizes: { key: JsonEditorSize; label: string }[] = [\n    { key: 'sm', label: 'Small' },\n    { key: 'md', label: 'Medium (Default)' },\n    { key: 'lg', label: 'Large' },\n];\n\nconst SizeVariants: React.FC = () => {\n    const { isDark } = useStoryTheme();\n    const [data, setData] = useState<Record<string, JsonValue>>({\n        sm: { ...sampleData as Record<string, JsonValue> },\n        md: { ...sampleData as Record<string, JsonValue> },\n        lg: { ...sampleData as Record<string, JsonValue> },\n    });\n\n    return (\n        <ComponentDemo title=\"Size Variants\" description=\"Three size options for different use cases\" centered={false}>\n            <div className=\"w-full space-y-6 p-4\">\n                {sizes.map(({ key, label }) => (\n                    <div key={key}>\n                        <p className={cn('text-sm mb-2 font-medium', { 'text-gray-400': isDark, 'text-gray-600': !isDark })}>{label}</p>\n                        <JsonEditor\n                            value={data[key]}\n                            onChange={val => setData(prev => ({ ...prev, [key]: val }))}\n                            size={key}\n                            expandDepth={1}\n                        />\n                    </div>\n                ))}\n            </div>\n        </ComponentDemo>\n    );\n};\n\nexport default SizeVariants;\n"
        },
        {
          "title": "SortedKeys",
          "code": "import cn from 'classnames';\nimport React, { useState } from 'react';\nimport { JsonEditor } from '../../../components';\nimport type { JsonValue } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\n\nconst unsortedData: JsonValue = {\n    zebra: 'last animal',\n    apple: 'first fruit',\n    mango: 'tropical fruit',\n    banana: 'yellow fruit',\n    config: {\n        zIndex: 100,\n        animation: true,\n        border: '1px solid',\n    },\n};\n\nconst code = `<JsonEditor value={data} onChange={setData} sortKeys />`;\n\nconst SortedKeys: React.FC = () => {\n    const { isDark } = useStoryTheme();\n    const [data1, setData1] = useState<JsonValue>({ ...unsortedData as Record<string, JsonValue> });\n    const [data2, setData2] = useState<JsonValue>({ ...unsortedData as Record<string, JsonValue> });\n\n    return (\n        <>\n            <ComponentDemo title=\"Sorted Keys\" description=\"Automatically sort object keys alphabetically\" centered={false}>\n                <div className=\"w-full space-y-6 p-4\">\n                    <div>\n                        <p className={cn('text-sm mb-2 font-medium', { 'text-gray-400': isDark, 'text-gray-600': !isDark })}>Default (insertion order)</p>\n                        <JsonEditor value={data1} onChange={setData1} expandDepth={2} />\n                    </div>\n                    <div>\n                        <p className={cn('text-sm mb-2 font-medium', { 'text-gray-400': isDark, 'text-gray-600': !isDark })}>Sorted keys</p>\n                        <JsonEditor value={data2} onChange={setData2} sortKeys expandDepth={2} />\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default SortedKeys;\n"
        },
        {
          "title": "TypeShowcase",
          "code": "import React, { useState } from 'react';\nimport type { JsonValue } from '../../../components';\nimport { JsonEditor } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { typeShowcaseData } from './json-editor-story-data';\n\nconst code = `import { JsonEditor } from 'fluxo-ui';\n\n<JsonEditor\n  value={data}\n  onChange={setData}\n  showDataTypes\n  allowTypeChange\n/>`;\n\nconst TypeShowcase: React.FC = () => {\n    const [data, setData] = useState<JsonValue>(typeShowcaseData);\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Data Types & Type Badges\"\n                description=\"All supported data types with type badges and type changing\"\n                centered={false}\n            >\n                <div className=\"w-full p-4\">\n                    <JsonEditor value={data} onChange={setData} showDataTypes allowTypeChange expandDepth={1} />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default TypeShowcase;\n"
        }
      ],
      "props": {
        "jsonEditorProps": {
          "value": {
            "type": "JsonValue",
            "description": "The JSON value to display and edit",
            "default": "-"
          },
          "onChange": {
            "type": "(value: JsonValue) => void",
            "description": "Callback when the value changes",
            "default": "-"
          },
          "allowEditValue": {
            "type": "boolean",
            "default": "true",
            "description": "Allow editing values"
          },
          "allowEditKey": {
            "type": "boolean",
            "default": "true",
            "description": "Allow editing/renaming keys"
          },
          "allowRemove": {
            "type": "boolean",
            "default": "true",
            "description": "Allow removing properties/items"
          },
          "allowInsert": {
            "type": "boolean",
            "default": "true",
            "description": "Allow adding new properties/items"
          },
          "allowTypeChange": {
            "type": "boolean",
            "default": "false",
            "description": "Show type badges with type changing"
          },
          "allowCopy": {
            "type": "boolean",
            "default": "true",
            "description": "Allow copying values to clipboard"
          },
          "allowSearch": {
            "type": "boolean",
            "default": "true",
            "description": "Show search in toolbar"
          },
          "readOnly": {
            "type": "boolean",
            "default": "false",
            "description": "Disable all editing"
          },
          "expandDepth": {
            "type": "number",
            "default": "1",
            "description": "Initial depth to auto-expand"
          },
          "size": {
            "type": "'sm' | 'md' | 'lg'",
            "default": "'md'",
            "description": "Font and spacing size"
          },
          "maxHeight": {
            "type": "string | number",
            "description": "Max height with scroll overflow",
            "default": "-"
          },
          "showDataTypes": {
            "type": "boolean",
            "default": "false",
            "description": "Show type labels next to values"
          },
          "showItemCount": {
            "type": "boolean",
            "default": "true",
            "description": "Show item count for objects/arrays"
          },
          "showToolbar": {
            "type": "boolean",
            "default": "true",
            "description": "Show the toolbar with search and actions"
          },
          "sortKeys": {
            "type": "boolean",
            "default": "false",
            "description": "Sort object keys alphabetically"
          },
          "className": {
            "type": "string",
            "description": "Additional CSS class",
            "default": "-"
          },
          "id": {
            "type": "string",
            "description": "HTML id attribute",
            "default": "-"
          },
          "ariaLabel": {
            "type": "string",
            "description": "Accessible label",
            "default": "-"
          }
        }
      },
      "storyDir": "json-editor"
    },
    "KanbanBoard": {
      "name": "KanbanBoard",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React from 'react';\nimport { KanbanBoard } from '../../../components/kanban-board';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { basicCards, basicColumns } from './kanban-story-data';\n\nconst code = `import { KanbanBoard } from 'fluxo-ui';\nimport type { KanbanCardData, KanbanColumnData } from 'fluxo-ui';\n\nconst columns: KanbanColumnData[] = [\n  { id: 'backlog', title: 'Backlog', color: '#94a3b8' },\n  { id: 'todo', title: 'To Do', color: '#3b82f6' },\n  { id: 'in-progress', title: 'In Progress', color: '#f59e0b', limit: 3 },\n  { id: 'review', title: 'Review', color: '#8b5cf6' },\n  { id: 'done', title: 'Done', color: '#10b981' },\n];\n\nconst cards: KanbanCardData[] = [\n  {\n    id: '1',\n    title: 'Design landing page mockup',\n    columnId: 'backlog',\n    order: 0,\n    priority: 'medium',\n    labels: [{ id: 'design', text: 'Design', color: '#8b5cf6' }],\n    assignee: { id: 'a1', name: 'Alice Martin' },\n  },\n  // ...more cards\n];\n\n<KanbanBoard\n  columns={columns}\n  cards={cards}\n  draggable\n  showCardCount\n  showColumnLimit\n  showSearch\n  allowCollapse\n/>`;\n\nconst BasicUsage: React.FC = () => (\n    <>\n        <ComponentDemo\n            title=\"Basic Kanban Board\"\n            description=\"Standard board with drag-and-drop, card count, search, and collapsible columns.\"\n            centered={false}\n        >\n            <KanbanBoard\n                columns={basicColumns}\n                cards={basicCards}\n                draggable\n                showCardCount\n                showColumnLimit\n                showSearch\n                allowCollapse\n                onCardClick={(e) => console.log('Clicked:', e.card.title)}\n            />\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default BasicUsage;\n"
        },
        {
          "title": "BlockedCards",
          "code": "import React from 'react';\nimport { KanbanBoard } from '../../../components/kanban-board';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { blockedColumns, blockedCards } from './kanban-story-data';\n\nconst code = `const cards: KanbanCardData[] = [\n  {\n    id: 'b1',\n    title: 'Implement SSO integration',\n    columnId: 'in-progress',\n    order: 0,\n    priority: 'high',\n    blocked: true,\n    color: '#ef4444',\n    description: 'Blocked: Waiting for IdP credentials.',\n  },\n  {\n    id: 'b2',\n    title: 'Mobile push notifications',\n    columnId: 'in-progress',\n    order: 1,\n    priority: 'medium',\n    blocked: true,\n  },\n  // non-blocked cards...\n];\n\n<KanbanBoard\n  columns={columns}\n  cards={cards}\n  cardSize=\"detailed\"\n  draggable\n  showCardCount\n/>`;\n\nconst BlockedCards: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Blocked Cards\" description=\"Set blocked: true on a card to visually indicate it is blocked. Combine with color to add a colored left border.\" centered={false}>\n            <KanbanBoard\n                columns={blockedColumns}\n                cards={blockedCards}\n                cardSize=\"detailed\"\n                draggable\n                showCardCount\n            />\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default BlockedCards;\n"
        },
        {
          "title": "CardActions",
          "code": "import cn from 'classnames';\nimport React from 'react';\nimport { KanbanBoard } from '../../../components/kanban-board';\nimport type { KanbanCardData, KanbanColumnData } from '../../../components/kanban-board';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\nimport { compactColumns, compactCards } from './kanban-story-data';\n\nconst code = `<KanbanBoard\n  columns={columns}\n  cards={cards}\n  draggable\n  showCardCount\n  cardActionsTemplate={(card, column) => (\n    <div className=\"flex items-center gap-1\">\n      <button\n        className=\"px-2 py-0.5 text-xs rounded hover:bg-gray-100\"\n        onClick={() => console.log('Edit:', card.title)}\n      >\n        Edit\n      </button>\n      <button\n        className=\"px-2 py-0.5 text-xs rounded hover:bg-gray-100\"\n        onClick={() => console.log('Archive:', card.title)}\n      >\n        Archive\n      </button>\n    </div>\n  )}\n/>`;\n\nconst CardActions: React.FC = () => {\n    const { isDark } = useStoryTheme();\n\n    return (\n        <>\n            <ComponentDemo title=\"Custom Card Actions\" description=\"Use cardActionsTemplate to add action buttons in the card footer area.\" centered={false}>\n                <KanbanBoard\n                    columns={compactColumns}\n                    cards={compactCards}\n                    draggable\n                    showCardCount\n                    cardActionsTemplate={(card: KanbanCardData, _column: KanbanColumnData) => (\n                        <div className=\"flex items-center gap-1 mt-1\">\n                            <button\n                                className={cn('px-2 py-0.5 text-[11px] rounded transition-colors', {\n                                    'hover:bg-white/10 text-gray-400': isDark,\n                                    'hover:bg-gray-100 text-gray-500': !isDark,\n                                })}\n                                onClick={(e) => { e.stopPropagation(); console.log('Edit:', card.title); }}\n                                type=\"button\"\n                            >\n                                Edit\n                            </button>\n                            <button\n                                className={cn('px-2 py-0.5 text-[11px] rounded transition-colors', {\n                                    'hover:bg-white/10 text-gray-400': isDark,\n                                    'hover:bg-gray-100 text-gray-500': !isDark,\n                                })}\n                                onClick={(e) => { e.stopPropagation(); console.log('Archive:', card.title); }}\n                                type=\"button\"\n                            >\n                                Archive\n                            </button>\n                        </div>\n                    )}\n                />\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default CardActions;\n"
        },
        {
          "title": "CollapsibleColumns",
          "code": "import React, { useState } from 'react';\nimport type { KanbanCardData, KanbanColumnData, KanbanColumnId } from '../../../components/kanban-board';\nimport { KanbanBoard } from '../../../components/kanban-board';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst columns: KanbanColumnData[] = [\n    { id: 'backlog', title: 'Backlog', color: '#94a3b8' },\n    { id: 'todo', title: 'To Do', color: '#3b82f6' },\n    { id: 'in-progress', title: 'In Progress', color: '#f59e0b' },\n    { id: 'review', title: 'Code Review', color: '#8b5cf6', collapsed: true },\n    { id: 'done', title: 'Done', color: '#10b981' },\n];\n\nconst cards: KanbanCardData[] = [\n    { id: '1', title: 'Design landing page mockup', columnId: 'backlog', order: 0, priority: 'medium' },\n    { id: '2', title: 'Implement user auth API', columnId: 'backlog', order: 1, priority: 'high' },\n    { id: '3', title: 'Set up CI/CD pipeline', columnId: 'todo', order: 0, priority: 'low' },\n    { id: '4', title: 'Write unit tests for auth', columnId: 'todo', order: 1, priority: 'medium' },\n    { id: '5', title: 'Build dashboard layout', columnId: 'in-progress', order: 0, priority: 'high' },\n    { id: '6', title: 'API rate limiting', columnId: 'in-progress', order: 1, priority: 'critical' },\n    { id: '7', title: 'Review PR #142', columnId: 'review', order: 0, priority: 'medium' },\n    { id: '8', title: 'Database migration script', columnId: 'done', order: 0, priority: 'low' },\n    { id: '9', title: 'Setup logging infrastructure', columnId: 'done', order: 1, priority: 'medium' },\n];\n\nconst code = `import { KanbanBoard } from 'fluxo-ui';\nimport type { KanbanColumnData, KanbanCardData, KanbanColumnId } from 'fluxo-ui';\n\nconst columns: KanbanColumnData[] = [\n  { id: 'backlog', title: 'Backlog', color: '#94a3b8' },\n  { id: 'todo', title: 'To Do', color: '#3b82f6' },\n  { id: 'in-progress', title: 'In Progress', color: '#f59e0b' },\n  { id: 'review', title: 'Code Review', color: '#8b5cf6', collapsed: true },\n  { id: 'done', title: 'Done', color: '#10b981' },\n];\n\n// Set collapsed: true on a column to have it collapsed by default.\n// Enable allowCollapse to show collapse/expand toggle in column headers.\n// Collapsed columns shrink to ~40px with a vertically rotated title.\n// Click on a collapsed column to expand it.\n\n<KanbanBoard\n  columns={columns}\n  cards={cards}\n  allowCollapse\n  showCardCount\n  onColumnCollapse={(columnId, collapsed) => {\n    console.log(columnId, collapsed ? 'collapsed' : 'expanded');\n  }}\n/>`;\n\nconst CollapsibleColumns: React.FC = () => {\n    const [lastEvent, setLastEvent] = useState('');\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Collapsible Columns\"\n                description=\"Click the collapse button in the column header to collapse a column. The 'Code Review' column starts collapsed. Collapsed columns display a rotated vertical title and remaining columns fill the available space. Click a collapsed column to expand it.\"\n                centered={false}\n            >\n                <KanbanBoard\n                    columns={columns}\n                    cards={cards}\n                    allowCollapse\n                    showCardCount\n                    onColumnCollapse={(columnId: KanbanColumnId, collapsed: boolean) => {\n                        setLastEvent(`${String(columnId)} ${collapsed ? 'collapsed' : 'expanded'}`);\n                    }}\n                />\n                {lastEvent && (\n                    <p className=\"mt-2 text-xs text-gray-500\">\n                        Last event: <strong>{lastEvent}</strong>\n                    </p>\n                )}\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default CollapsibleColumns;\n"
        },
        {
          "title": "ColumnLimits",
          "code": "import React from 'react';\nimport { KanbanBoard } from '../../../components/kanban-board';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { wipColumns, wipCards } from './kanban-story-data';\n\nconst code = `const columns: KanbanColumnData[] = [\n  { id: 'todo', title: 'To Do', color: '#3b82f6' },\n  { id: 'dev', title: 'Development', color: '#f59e0b', limit: 2 },\n  { id: 'qa', title: 'QA', color: '#8b5cf6', limit: 2 },\n  { id: 'done', title: 'Done', color: '#10b981' },\n];\n\n<KanbanBoard\n  columns={columns}\n  cards={cards}\n  draggable\n  showCardCount\n  showColumnLimit\n/>`;\n\nconst ColumnLimits: React.FC = () => (\n    <>\n        <ComponentDemo title=\"WIP Limits\" description=\"Set limit on columns to enforce work-in-progress constraints. Columns exceeding their limit display a visual warning.\" centered={false}>\n            <KanbanBoard\n                columns={wipColumns}\n                cards={wipCards}\n                draggable\n                showCardCount\n                showColumnLimit\n            />\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default ColumnLimits;\n"
        },
        {
          "title": "CompactMode",
          "code": "import React from 'react';\nimport { KanbanBoard } from '../../../components/kanban-board';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { compactColumns, compactCards } from './kanban-story-data';\n\nconst code = `<KanbanBoard\n  columns={columns}\n  cards={cards}\n  cardSize=\"compact\"\n  draggable\n  showCardCount\n  columnWidth={240}\n/>`;\n\nconst CompactMode: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Compact Mode\" description=\"Minimal card display ideal for high-density boards with many items.\" centered={false}>\n            <KanbanBoard\n                columns={compactColumns}\n                cards={compactCards}\n                cardSize=\"compact\"\n                draggable\n                showCardCount\n                columnWidth={240}\n            />\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default CompactMode;\n"
        },
        {
          "title": "CustomColumnHeader",
          "code": "import cn from 'classnames';\nimport React from 'react';\nimport { KanbanBoard } from '../../../components/kanban-board';\nimport type { KanbanColumnData } from '../../../components/kanban-board';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\nimport { basicColumns, basicCards } from './kanban-story-data';\n\nconst code = `<KanbanBoard\n  columns={columns}\n  cards={cards}\n  draggable\n  columnHeaderTemplate={(column, cardCount) => (\n    <div className=\"flex items-center gap-2 px-3 py-2\">\n      <span\n        className=\"w-3 h-3 rounded-full\"\n        style={{ backgroundColor: column.color }}\n      />\n      <span className=\"text-sm font-semibold flex-1\">\n        {column.title}\n      </span>\n      <span className=\"text-xs px-2 py-0.5 rounded-full bg-gray-100\">\n        {cardCount}\n      </span>\n    </div>\n  )}\n  emptyColumnTemplate={(column) => (\n    <div className=\"text-center py-8 text-sm text-gray-400 italic\">\n      No items in {column.title}\n    </div>\n  )}\n/>`;\n\nconst CustomColumnHeader: React.FC = () => {\n    const { isDark } = useStoryTheme();\n\n    return (\n        <>\n            <ComponentDemo title=\"Custom Column Header & Empty State\" description=\"Use columnHeaderTemplate and emptyColumnTemplate for full control over column rendering.\" centered={false}>\n                <KanbanBoard\n                    columns={basicColumns}\n                    cards={basicCards}\n                    draggable\n                    columnHeaderTemplate={(column: KanbanColumnData, cardCount: number) => (\n                        <div className=\"flex items-center gap-2 px-3 py-2.5\">\n                            <span\n                                className=\"w-3 h-3 rounded-full shrink-0\"\n                                style={{ backgroundColor: column.color }}\n                            />\n                            <span className={cn('text-sm font-semibold flex-1', { 'text-gray-100': isDark, 'text-gray-800': !isDark })}>\n                                {column.title}\n                            </span>\n                            <span className={cn('text-[11px] font-medium px-2 py-0.5 rounded-full', {\n                                'bg-white/10 text-gray-400': isDark,\n                                'bg-gray-100 text-gray-500': !isDark,\n                            })}>\n                                {cardCount}\n                            </span>\n                        </div>\n                    )}\n                    emptyColumnTemplate={(column: KanbanColumnData) => (\n                        <div className={cn('text-center py-8 text-sm italic', { 'text-gray-600': isDark, 'text-gray-400': !isDark })}>\n                            No items in {column.title}\n                        </div>\n                    )}\n                />\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default CustomColumnHeader;\n"
        },
        {
          "title": "CustomTemplates",
          "code": "import cn from 'classnames';\nimport React from 'react';\nimport { KanbanBoard } from '../../../components/kanban-board';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\nimport { compactColumns, compactCards } from './kanban-story-data';\n\nconst code = `<KanbanBoard\n  columns={columns}\n  cards={cards}\n  draggable\n  showCardCount\n  columnWidth={260}\n  cardTemplate={(card) => (\n    <div className=\"flex items-center gap-3 p-2\">\n      <span\n        className={cn('w-2 h-2 rounded-full shrink-0', {\n          'bg-red-500': card.priority === 'high' || card.priority === 'critical',\n          'bg-yellow-500': card.priority === 'medium',\n          'bg-green-500': card.priority === 'low',\n        })}\n      />\n      <span className=\"text-sm font-medium truncate\">\n        {card.title}\n      </span>\n    </div>\n  )}\n/>`;\n\nconst CustomTemplates: React.FC = () => {\n    const { isDark } = useStoryTheme();\n\n    return (\n        <>\n            <ComponentDemo title=\"Custom Card Template\" description=\"Use cardTemplate to render fully custom card content with any layout.\" centered={false}>\n                <KanbanBoard\n                    columns={compactColumns}\n                    cards={compactCards}\n                    draggable\n                    showCardCount\n                    columnWidth={260}\n                    cardTemplate={(card) => (\n                        <div className=\"flex items-center gap-3 p-2\">\n                            <span\n                                className={cn('w-2 h-2 rounded-full shrink-0', {\n                                    'bg-red-500': card.priority === 'high' || card.priority === 'critical',\n                                    'bg-yellow-500': card.priority === 'medium',\n                                    'bg-green-500': card.priority === 'low',\n                                })}\n                            />\n                            <span className={cn('text-sm font-medium truncate', { 'text-gray-200': isDark, 'text-gray-700': !isDark })}>\n                                {card.title}\n                            </span>\n                        </div>\n                    )}\n                />\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default CustomTemplates;\n"
        },
        {
          "title": "DetailedCards",
          "code": "import React from 'react';\nimport { KanbanBoard } from '../../../components/kanban-board';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { detailedColumns, detailedCards } from './kanban-story-data';\n\nconst code = `<KanbanBoard\n  columns={columns}\n  cards={cards}\n  cardSize=\"detailed\"\n  draggable\n  showCardCount\n  showColumnLimit\n  allowCollapse\n/>\n\n// Card data for detailed view includes:\nconst card: KanbanCardData = {\n  id: 'd1',\n  title: 'Redesign dashboard',\n  columnId: 'todo',\n  order: 0,\n  description: 'Update all components to match new brand.',\n  priority: 'high',\n  labels: [\n    { id: 'design', text: 'Design', color: '#8b5cf6' },\n    { id: 'frontend', text: 'Frontend', color: '#3b82f6' },\n  ],\n  assignees: [\n    { id: 'a1', name: 'Alice Martin' },\n    { id: 'a2', name: 'Bob Chen' },\n  ],\n  dueDate: new Date('2025-04-15'),\n  progress: 30,\n  subtaskCount: 12,\n  subtaskCompleted: 4,\n  commentCount: 8,\n  attachmentCount: 3,\n};`;\n\nconst DetailedCards: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Detailed Card View\" description=\"Cards with descriptions, progress bars, labels, subtask counts, and assignee stacking.\" centered={false}>\n            <KanbanBoard\n                columns={detailedColumns}\n                cards={detailedCards}\n                cardSize=\"detailed\"\n                draggable\n                showCardCount\n                showColumnLimit\n                allowCollapse\n            />\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default DetailedCards;\n"
        },
        {
          "title": "InteractiveBoard",
          "code": "import cn from 'classnames';\nimport React, { useCallback, useState } from 'react';\nimport { KanbanBoard } from '../../../components/kanban-board';\nimport type {\n    KanbanCardData,\n    KanbanCardMoveEvent,\n    KanbanCardReorderEvent,\n    KanbanCardCreateEvent,\n    KanbanCardDeleteEvent,\n    KanbanCardClickEvent,\n    KanbanColumnData,\n    KanbanColumnCreateEvent,\n    KanbanColumnDeleteEvent,\n    KanbanColumnUpdateEvent,\n    KanbanColumnReorderEvent,\n} from '../../../components/kanban-board';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\nimport { basicColumns, basicCards, getNextId } from './kanban-story-data';\n\nconst code = `const [cards, setCards] = useState<KanbanCardData[]>(initialCards);\nconst [columns, setColumns] = useState<KanbanColumnData[]>(initialColumns);\n\n<KanbanBoard\n  columns={columns}\n  cards={cards}\n  draggable\n  columnDraggable\n  allowAddCard\n  allowAddColumn\n  allowDeleteCard\n  allowDeleteColumn\n  allowEditColumn\n  allowCollapse\n  showCardCount\n  showColumnLimit\n  showSearch\n  onCardMove={(e) => {\n    setCards(prev => {\n      const without = prev.filter(c => c.id !== e.cardId);\n      const target = without\n        .filter(c => c.columnId === e.toColumnId)\n        .sort((a, b) => a.order - b.order);\n      const others = without.filter(c => c.columnId !== e.toColumnId);\n      const moved = { ...e.card, columnId: e.toColumnId, order: e.toIndex };\n      target.splice(e.toIndex, 0, moved);\n      return [...others, ...target.map((c, i) => ({ ...c, order: i }))];\n    });\n  }}\n  onCardReorder={(e) => {\n    setCards(prev => {\n      const other = prev.filter(c => c.columnId !== e.columnId);\n      return [...other, ...e.cards.map((c, i) => ({ ...c, order: i }))];\n    });\n  }}\n  onCardCreate={(e) => {\n    setCards(prev => [...prev, {\n      id: \\`new-\\${Date.now()}\\`,\n      title: e.title,\n      columnId: e.columnId,\n      order: prev.filter(c => c.columnId === e.columnId).length,\n    }]);\n  }}\n  onCardDelete={(e) => setCards(prev => prev.filter(c => c.id !== e.card.id))}\n  onColumnCreate={(e) => setColumns(prev => [...prev, { id: \\`col-\\${Date.now()}\\`, title: e.title }])}\n  onColumnDelete={(e) => {\n    setColumns(prev => prev.filter(c => c.id !== e.column.id));\n    setCards(prev => prev.filter(c => c.columnId !== e.column.id));\n  }}\n  onColumnUpdate={(e) => setColumns(prev =>\n    prev.map(c => c.id === e.column.id ? { ...c, [e.field]: e.value } : c)\n  )}\n  onColumnReorder={(e) => setColumns(e.columns)}\n/>`;\n\nconst InteractiveBoard: React.FC = () => {\n    const { isDark } = useStoryTheme();\n    const [interactiveCards, setInteractiveCards] = useState<KanbanCardData[]>(basicCards);\n    const [interactiveColumns, setInteractiveColumns] = useState<KanbanColumnData[]>(basicColumns);\n    const [lastEvent, setLastEvent] = useState('');\n\n    const handleCardMove = useCallback((event: KanbanCardMoveEvent) => {\n        setInteractiveCards((prev) => {\n            const withoutCard = prev.filter((c) => c.id !== event.cardId);\n            const targetCards = withoutCard\n                .filter((c) => c.columnId === event.toColumnId)\n                .sort((a, b) => a.order - b.order);\n            const otherCards = withoutCard.filter((c) => c.columnId !== event.toColumnId);\n            const movedCard = { ...event.card, columnId: event.toColumnId, order: event.toIndex };\n            targetCards.splice(event.toIndex, 0, movedCard);\n            const reordered = targetCards.map((c, i) => ({ ...c, order: i }));\n            return [...otherCards, ...reordered];\n        });\n        setLastEvent(`Moved \"${event.card.title}\" to column \"${event.toColumnId}\"`);\n    }, []);\n\n    const handleCardReorder = useCallback((event: KanbanCardReorderEvent) => {\n        setInteractiveCards((prev) => {\n            const other = prev.filter((c) => c.columnId !== event.columnId);\n            const reordered = event.cards.map((c, i) => ({ ...c, order: i }));\n            return [...other, ...reordered];\n        });\n    }, []);\n\n    const handleCardCreate = useCallback((event: KanbanCardCreateEvent) => {\n        const newCard: KanbanCardData = {\n            id: getNextId(),\n            title: event.title,\n            columnId: event.columnId,\n            order: interactiveCards.filter((c) => c.columnId === event.columnId).length,\n        };\n        setInteractiveCards((prev) => [...prev, newCard]);\n        setLastEvent(`Created card \"${event.title}\"`);\n    }, [interactiveCards]);\n\n    const handleCardDelete = useCallback((event: KanbanCardDeleteEvent) => {\n        setInteractiveCards((prev) => prev.filter((c) => c.id !== event.card.id));\n        setLastEvent(`Deleted card \"${event.card.title}\"`);\n    }, []);\n\n    const handleCardClick = useCallback((event: KanbanCardClickEvent) => {\n        setLastEvent(`Clicked: \"${event.card.title}\"`);\n    }, []);\n\n    const handleColumnCreate = useCallback((event: KanbanColumnCreateEvent) => {\n        const newCol: KanbanColumnData = { id: getNextId(), title: event.title };\n        setInteractiveColumns((prev) => [...prev, newCol]);\n        setLastEvent(`Created column \"${event.title}\"`);\n    }, []);\n\n    const handleColumnDelete = useCallback((event: KanbanColumnDeleteEvent) => {\n        setInteractiveColumns((prev) => prev.filter((c) => c.id !== event.column.id));\n        setInteractiveCards((prev) => prev.filter((c) => c.columnId !== event.column.id));\n        setLastEvent(`Deleted column \"${event.column.title}\"`);\n    }, []);\n\n    const handleColumnUpdate = useCallback((event: KanbanColumnUpdateEvent) => {\n        setInteractiveColumns((prev) =>\n            prev.map((c) => (c.id === event.column.id ? { ...c, [event.field]: event.value } : c)),\n        );\n    }, []);\n\n    const handleColumnReorder = useCallback((event: KanbanColumnReorderEvent) => {\n        setInteractiveColumns(event.columns);\n    }, []);\n\n    return (\n        <>\n            <ComponentDemo title=\"Interactive Board\" description=\"Full interactive demo: drag cards, add/delete cards and columns, edit column titles, reorder columns.\" centered={false}>\n                <div className=\"space-y-3\">\n                    <KanbanBoard\n                        columns={interactiveColumns}\n                        cards={interactiveCards}\n                        draggable\n                        columnDraggable\n                        allowAddCard\n                        allowAddColumn\n                        allowDeleteCard\n                        allowDeleteColumn\n                        allowEditColumn\n                        allowCollapse\n                        showCardCount\n                        showColumnLimit\n                        showSearch\n                        onCardMove={handleCardMove}\n                        onCardReorder={handleCardReorder}\n                        onCardCreate={handleCardCreate}\n                        onCardDelete={handleCardDelete}\n                        onCardClick={handleCardClick}\n                        onColumnCreate={handleColumnCreate}\n                        onColumnDelete={handleColumnDelete}\n                        onColumnUpdate={handleColumnUpdate}\n                        onColumnReorder={handleColumnReorder}\n                    />\n                    {lastEvent && (\n                        <div className={cn('text-sm px-4 py-2 rounded border', {\n                            'border-blue-800 bg-blue-900/30 text-blue-300': isDark,\n                            'border-blue-200 bg-blue-50 text-blue-800': !isDark,\n                        })}>\n                            Event: {lastEvent}\n                        </div>\n                    )}\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default InteractiveBoard;\n"
        },
        {
          "title": "LockedColumns",
          "code": "import React from 'react';\nimport { KanbanBoard } from '../../../components/kanban-board';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { lockedColumns, lockedCards } from './kanban-story-data';\n\nconst code = `const columns: KanbanColumnData[] = [\n  { id: 'new', title: 'New', color: '#3b82f6' },\n  { id: 'active', title: 'Active', color: '#f59e0b' },\n  { id: 'archived', title: 'Archived', color: '#94a3b8', locked: true },\n];\n\n<KanbanBoard\n  columns={columns}\n  cards={cards}\n  draggable\n  allowAddCard\n  showCardCount\n/>`;\n\nconst LockedColumns: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Locked Columns\" description=\"Set locked: true on a column to prevent drag-and-drop and hide add/delete controls. Ideal for archival or read-only columns.\" centered={false}>\n            <KanbanBoard\n                columns={lockedColumns}\n                cards={lockedCards}\n                draggable\n                allowAddCard\n                showCardCount\n            />\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default LockedColumns;\n"
        },
        {
          "title": "StickyHeaders",
          "code": "import React from 'react';\nimport { KanbanBoard } from '../../../components/kanban-board';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { basicColumns, basicCards } from './kanban-story-data';\n\nconst code = `<KanbanBoard\n  columns={columns}\n  cards={cards}\n  draggable\n  showCardCount\n  stickyColumnHeaders\n  maxColumnHeight={300}\n/>`;\n\nconst StickyHeaders: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Sticky Column Headers\" description=\"Enable stickyColumnHeaders with maxColumnHeight to keep column headers visible while scrolling through cards.\" centered={false}>\n            <KanbanBoard\n                columns={basicColumns}\n                cards={basicCards}\n                draggable\n                showCardCount\n                stickyColumnHeaders\n                maxColumnHeight={300}\n            />\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default StickyHeaders;\n"
        },
        {
          "title": "VerticalLayout",
          "code": "import React from 'react';\nimport { KanbanBoard } from '../../../components/kanban-board';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { verticalColumns, verticalCards } from './kanban-story-data';\n\nconst code = `<KanbanBoard\n  columns={columns}\n  cards={cards}\n  layout=\"vertical\"\n  draggable\n  showCardCount\n  allowCollapse\n/>`;\n\nconst VerticalLayout: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Vertical Layout\" description=\"Stack columns vertically instead of horizontally. Useful for priority triage or narrow containers.\" centered={false}>\n            <KanbanBoard\n                columns={verticalColumns}\n                cards={verticalCards}\n                layout=\"vertical\"\n                draggable\n                showCardCount\n                allowCollapse\n            />\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default VerticalLayout;\n"
        }
      ],
      "props": {
        "boardProps": {
          "columns": {
            "type": "KanbanColumnData[]",
            "required": true,
            "description": "Array of column definitions with id, title, color, icon, limit, collapsed, locked."
          },
          "cards": {
            "type": "KanbanCardData[]",
            "required": true,
            "description": "Array of card data with id, title, columnId, order, priority, labels, assignees, etc."
          },
          "layout": {
            "type": "\"horizontal\" | \"vertical\"",
            "default": "horizontal",
            "description": "Board layout direction."
          },
          "cardSize": {
            "type": "\"compact\" | \"default\" | \"detailed\"",
            "default": "default",
            "description": "Card display density. Compact hides labels/progress, detailed shows descriptions."
          },
          "className": {
            "type": "string",
            "description": "Additional CSS class for the board container."
          },
          "columnWidth": {
            "type": "number | string",
            "description": "Fixed column width (px or CSS value)."
          },
          "columnMinHeight": {
            "type": "number | string",
            "description": "Minimum column body height."
          },
          "maxColumnHeight": {
            "type": "number | string",
            "description": "Maximum column body scroll height."
          },
          "draggable": {
            "type": "boolean",
            "default": true,
            "description": "Enable drag-and-drop for cards."
          },
          "columnDraggable": {
            "type": "boolean",
            "default": false,
            "description": "Enable drag-and-drop reordering of columns."
          },
          "allowAddCard": {
            "type": "boolean",
            "default": false,
            "description": "Show \"Add card\" button in each column footer."
          },
          "allowAddColumn": {
            "type": "boolean",
            "default": false,
            "description": "Show \"Add Column\" button at the end."
          },
          "allowDeleteCard": {
            "type": "boolean",
            "default": false,
            "description": "Show delete button on card hover."
          },
          "allowDeleteColumn": {
            "type": "boolean",
            "default": false,
            "description": "Show delete button in column headers."
          },
          "allowEditColumn": {
            "type": "boolean",
            "default": false,
            "description": "Enable double-click to edit column title."
          },
          "allowCollapse": {
            "type": "boolean",
            "default": false,
            "description": "Show collapse/expand toggle in column headers."
          },
          "showCardCount": {
            "type": "boolean",
            "default": false,
            "description": "Display card count badge in column headers."
          },
          "showColumnLimit": {
            "type": "boolean",
            "default": false,
            "description": "Display WIP limit alongside card count."
          },
          "showSearch": {
            "type": "boolean",
            "default": false,
            "description": "Show search input above the board."
          },
          "stickyColumnHeaders": {
            "type": "boolean",
            "default": false,
            "description": "Make column headers sticky on scroll."
          },
          "cardTemplate": {
            "type": "(card, column) => ReactNode",
            "description": "Custom render function for card content."
          },
          "columnHeaderTemplate": {
            "type": "(column, count) => ReactNode",
            "description": "Custom render function for column headers."
          },
          "columnFooterTemplate": {
            "type": "(column, cards) => ReactNode",
            "description": "Custom render function for column footers."
          },
          "emptyColumnTemplate": {
            "type": "(column) => ReactNode",
            "description": "Custom render function for empty columns."
          },
          "cardActionsTemplate": {
            "type": "(card, column) => ReactNode",
            "description": "Custom actions rendered in card footer area."
          },
          "onCardMove": {
            "type": "(event: KanbanCardMoveEvent) => void",
            "description": "Called when a card is moved between columns."
          },
          "onCardReorder": {
            "type": "(event: KanbanCardReorderEvent) => void",
            "description": "Called when cards are reordered within a column."
          },
          "onCardClick": {
            "type": "(event: KanbanCardClickEvent) => void",
            "description": "Called when a card is clicked."
          },
          "onCardDoubleClick": {
            "type": "(event: KanbanCardClickEvent) => void",
            "description": "Called when a card is double-clicked."
          },
          "onCardCreate": {
            "type": "(event: KanbanCardCreateEvent) => void",
            "description": "Called when a new card is created via the add button."
          },
          "onCardDelete": {
            "type": "(event: KanbanCardDeleteEvent) => void",
            "description": "Called when a card delete button is clicked."
          },
          "onColumnReorder": {
            "type": "(event: KanbanColumnReorderEvent) => void",
            "description": "Called when columns are reordered via drag."
          },
          "onColumnCreate": {
            "type": "(event: KanbanColumnCreateEvent) => void",
            "description": "Called when a new column is created."
          },
          "onColumnDelete": {
            "type": "(event: KanbanColumnDeleteEvent) => void",
            "description": "Called when a column is deleted."
          },
          "onColumnUpdate": {
            "type": "(event: KanbanColumnUpdateEvent) => void",
            "description": "Called when a column title is edited."
          },
          "onColumnCollapse": {
            "type": "(columnId, collapsed) => void",
            "description": "Called when a column is collapsed or expanded."
          },
          "onSearchChange": {
            "type": "(filter: KanbanSearchFilter) => void",
            "description": "Called when the search input changes."
          }
        },
        "cardProps": {
          "id": {
            "type": "string | number",
            "required": true,
            "description": "Unique identifier for the card."
          },
          "title": {
            "type": "string",
            "required": true,
            "description": "Card title displayed prominently."
          },
          "columnId": {
            "type": "string | number",
            "required": true,
            "description": "ID of the column this card belongs to."
          },
          "order": {
            "type": "number",
            "required": true,
            "description": "Sort position within the column."
          },
          "description": {
            "type": "string",
            "description": "Card description shown in detailed view."
          },
          "priority": {
            "type": "\"critical\" | \"high\" | \"medium\" | \"low\" | \"none\"",
            "description": "Priority level with visual indicator."
          },
          "labels": {
            "type": "KanbanLabel[]",
            "description": "Color-coded labels shown on the card."
          },
          "assignee": {
            "type": "KanbanAssignee",
            "description": "Single assignee with name and optional avatar."
          },
          "assignees": {
            "type": "KanbanAssignee[]",
            "description": "Multiple assignees with stacked display."
          },
          "dueDate": {
            "type": "Date | string",
            "description": "Due date with overdue/soon indicators."
          },
          "coverImage": {
            "type": "string",
            "description": "Cover image URL shown in detailed mode."
          },
          "progress": {
            "type": "number",
            "description": "Completion percentage (0-100) shown as a progress bar."
          },
          "subtaskCount": {
            "type": "number",
            "description": "Total number of subtasks."
          },
          "subtaskCompleted": {
            "type": "number",
            "description": "Number of completed subtasks."
          },
          "commentCount": {
            "type": "number",
            "description": "Number of comments shown as a badge."
          },
          "attachmentCount": {
            "type": "number",
            "description": "Number of attachments shown as a badge."
          },
          "blocked": {
            "type": "boolean",
            "default": false,
            "description": "Mark the card as blocked with a visual overlay."
          },
          "color": {
            "type": "string",
            "description": "Left border color for the card."
          }
        },
        "columnProps": {
          "id": {
            "type": "string | number",
            "required": true,
            "description": "Unique identifier for the column."
          },
          "title": {
            "type": "string",
            "required": true,
            "description": "Column header title."
          },
          "color": {
            "type": "string",
            "description": "Accent color for the column header indicator."
          },
          "icon": {
            "type": "ReactNode",
            "description": "Icon displayed next to the column title."
          },
          "limit": {
            "type": "number",
            "description": "Maximum number of cards (WIP limit). Visual warning when exceeded."
          },
          "collapsed": {
            "type": "boolean",
            "default": false,
            "description": "Initial collapsed state of the column."
          },
          "locked": {
            "type": "boolean",
            "default": false,
            "description": "Prevent all interactions (drag, edit, add, delete)."
          }
        }
      },
      "storyDir": "kanban-board"
    },
    "Knob": {
      "name": "Knob",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React, { useState } from 'react';\nimport { Knob } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { Knob } from 'fluxo-ui';\n\nconst [value, setValue] = useState(72);\n\n<Knob value={value} label=\"CPU\" unit=\"%\" />\n<Knob value={value} interactive onChange={setValue} label=\"Volume\" />`;\n\nconst BasicUsage: React.FC = () => {\n    const [value, setValue] = useState(72);\n\n    return (\n        <>\n            <ComponentDemo title=\"Default Knob\" description=\"Read-only display and an interactive editor.\">\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 24 }}>\n                    <div style={{ display: 'flex', gap: 32, flexWrap: 'wrap', alignItems: 'center', justifyContent: 'center' }}>\n                        <Knob value={68} label=\"CPU\" unit=\"%\" />\n                        <Knob value={value} label=\"Volume\" unit=\"%\" interactive onChange={setValue} />\n                        <Knob value={42} label=\"Memory\" unit=\"%\" color=\"warning\" />\n                    </div>\n                    <div\n                        style={{\n                            padding: '12px 16px',\n                            background: 'var(--eui-bg-subtle)',\n                            border: '1px solid var(--eui-border-subtle)',\n                            borderRadius: 6,\n                            fontSize: 13,\n                        }}\n                    >\n                        Drag the middle knob, or use arrow keys when focused. Current value: <strong>{value}</strong>\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "Gauge",
          "code": "import React from 'react';\nimport { Knob } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<Knob value={72} arcStart={135} arcEnd={405} label=\"Speed\" unit=\"km/h\" color=\"primary\" />\n<Knob value={32} arcStart={180} arcEnd={360} label=\"Battery\" unit=\"%\" color=\"success\" />`;\n\nconst Gauge: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Partial Arcs\" description=\"Use arcStart and arcEnd to render gauges or half-circles.\">\n            <div style={{ display: 'flex', gap: 32, flexWrap: 'wrap', justifyContent: 'center' }}>\n                <Knob value={72} arcStart={135} arcEnd={405} label=\"Speed\" unit=\"km/h\" color=\"primary\" size=\"lg\" />\n                <Knob value={32} arcStart={180} arcEnd={360} label=\"Battery\" unit=\"%\" color=\"success\" size=\"lg\" />\n                <Knob value={88} arcStart={90} arcEnd={450} label=\"Storage\" unit=\"%\" color=\"info\" size=\"lg\" />\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default Gauge;\n"
        },
        {
          "title": "Interactive",
          "code": "import React, { useState } from 'react';\nimport { Knob } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `const [volume, setVolume] = useState(60);\n<Knob\n  value={volume}\n  interactive\n  step={5}\n  onChange={setVolume}\n  label=\"Volume\"\n  unit=\"%\"\n  color=\"primary\"\n/>`;\n\nconst Interactive: React.FC = () => {\n    const [volume, setVolume] = useState(60);\n    const [bass, setBass] = useState(45);\n    const [treble, setTreble] = useState(72);\n    return (\n        <>\n            <ComponentDemo\n                title=\"Interactive Editing\"\n                description=\"Drag the knob, use arrow keys, PageUp/PageDown for ×10 steps, or Home/End for min/max.\"\n            >\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 20 }}>\n                    <div style={{ display: 'flex', gap: 28, flexWrap: 'wrap', justifyContent: 'center' }}>\n                        <Knob value={volume} interactive step={5} onChange={setVolume} label=\"Volume\" unit=\"%\" />\n                        <Knob value={bass} interactive step={1} onChange={setBass} label=\"Bass\" color=\"success\" />\n                        <Knob value={treble} interactive step={1} onChange={setTreble} label=\"Treble\" color=\"warning\" />\n                    </div>\n                    <div\n                        style={{\n                            padding: '12px 16px',\n                            background: 'var(--eui-bg-subtle)',\n                            border: '1px solid var(--eui-border-subtle)',\n                            borderRadius: 6,\n                            fontSize: 13,\n                        }}\n                    >\n                        Volume: <strong>{volume}</strong> · Bass: <strong>{bass}</strong> · Treble: <strong>{treble}</strong>\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default Interactive;\n"
        },
        {
          "title": "Sizes",
          "code": "import React from 'react';\nimport { Knob } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<Knob value={64} size=\"xs\" label=\"XS\" />\n<Knob value={64} size=\"sm\" label=\"SM\" />\n<Knob value={64} size=\"md\" label=\"MD\" />\n<Knob value={64} size=\"lg\" label=\"LG\" />\n<Knob value={64} size=\"xl\" label=\"XL\" />`;\n\nconst Sizes: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Sizes\" description=\"Five preset sizes from xs through xl.\">\n            <div style={{ display: 'flex', gap: 24, flexWrap: 'wrap', alignItems: 'flex-end', justifyContent: 'center' }}>\n                <Knob value={64} size=\"xs\" label=\"XS\" />\n                <Knob value={64} size=\"sm\" label=\"SM\" />\n                <Knob value={64} size=\"md\" label=\"MD\" />\n                <Knob value={64} size=\"lg\" label=\"LG\" />\n                <Knob value={64} size=\"xl\" label=\"XL\" />\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default Sizes;\n"
        },
        {
          "title": "Variants",
          "code": "import React from 'react';\nimport { Knob } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<Knob value={72} variant=\"solid\" label=\"Solid\" />\n<Knob value={72} variant=\"gradient\" gradient={{ from: '#3b82f6', to: '#a855f7' }} label=\"Gradient\" />\n<Knob value={72} variant=\"striped\" label=\"Striped\" color=\"success\" />\n<Knob value={72} variant=\"dashed\" label=\"Dashed\" color=\"warning\" />\n<Knob value={72} variant=\"pie\" label=\"Pie\" color=\"danger\" />`;\n\nconst Variants: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Variants\" description=\"Solid, gradient, striped, dashed, and pie variants.\">\n            <div style={{ display: 'flex', gap: 32, flexWrap: 'wrap', justifyContent: 'center' }}>\n                <Knob value={72} variant=\"solid\" label=\"Solid\" />\n                <Knob\n                    value={72}\n                    variant=\"gradient\"\n                    gradient={{ from: '#3b82f6', to: '#a855f7' }}\n                    label=\"Gradient\"\n                />\n                <Knob value={72} variant=\"striped\" label=\"Striped\" color=\"success\" />\n                <Knob value={72} variant=\"dashed\" label=\"Dashed\" color=\"warning\" />\n                <Knob value={72} variant=\"pie\" label=\"Pie\" color=\"danger\" />\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default Variants;\n"
        }
      ],
      "props": {
        "knobProps": {
          "value": {
            "type": "number",
            "required": true,
            "description": "Current numeric value"
          },
          "min": {
            "type": "number",
            "default": "0",
            "description": "Minimum value"
          },
          "max": {
            "type": "number",
            "default": "100",
            "description": "Maximum value"
          },
          "size": {
            "type": "'xs' | 'sm' | 'md' | 'lg' | 'xl' | number",
            "default": "'md'",
            "description": "Preset size or arbitrary pixel diameter"
          },
          "strokeWidth": {
            "type": "number",
            "description": "Arc thickness in px (default scales with size)"
          },
          "variant": {
            "type": "'solid' | 'gradient' | 'striped' | 'dashed' | 'pie'",
            "default": "'solid'",
            "description": "Visual treatment of the filled arc"
          },
          "color": {
            "type": "'primary' | 'success' | 'warning' | 'danger' | 'info' | string",
            "default": "'primary'",
            "description": "Preset color or any CSS color"
          },
          "gradient": {
            "type": "{ from: string; to: string }",
            "description": "Gradient stops, used when variant is 'gradient'"
          },
          "trackColor": {
            "type": "string",
            "default": "var(--eui-border-subtle)",
            "description": "Color of the unfilled portion of the arc"
          },
          "arcStart": {
            "type": "number",
            "default": "0",
            "description": "Start angle in degrees (0 = top)"
          },
          "arcEnd": {
            "type": "number",
            "default": "360",
            "description": "End angle in degrees. Use values like 135-405 for a 3/4 gauge"
          },
          "roundedCaps": {
            "type": "boolean",
            "default": "true",
            "description": "Round vs flat stroke caps"
          },
          "showValue": {
            "type": "boolean",
            "default": "true",
            "description": "Show the numeric value in the center"
          },
          "valueFormatter": {
            "type": "(v: number) => string",
            "description": "Custom formatter for the displayed value"
          },
          "unit": {
            "type": "string",
            "description": "Unit suffix shown next to the value (e.g. '%', '°C')"
          },
          "label": {
            "type": "string",
            "description": "Text rendered above the value"
          },
          "subLabel": {
            "type": "string",
            "description": "Text rendered below the value"
          },
          "renderCenter": {
            "type": "() => ReactNode",
            "description": "Override the default center content"
          },
          "interactive": {
            "type": "boolean",
            "default": "false",
            "description": "Enable pointer drag and keyboard editing"
          },
          "step": {
            "type": "number",
            "default": "1",
            "description": "Increment step (interactive mode)"
          },
          "onChange": {
            "type": "(v: number) => void",
            "description": "Called in interactive mode on drag and arrow keys"
          },
          "disabled": {
            "type": "boolean",
            "default": "false",
            "description": "Disable interaction and dim the knob"
          },
          "id": {
            "type": "string",
            "description": "HTML id attribute"
          },
          "className": {
            "type": "string",
            "description": "Additional CSS classes"
          },
          "ariaLabel": {
            "type": "string",
            "description": "Accessible label for screen readers"
          }
        }
      },
      "storyDir": "knob"
    },
    "Lightbox": {
      "name": "Lightbox",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import cn from 'classnames';\nimport React from 'react';\nimport { Button, Lightbox } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\n\nconst code = `import { Lightbox } from 'fluxo-ui';\n\n<Lightbox\n  trigger=\"hover\"\n  content={<img src=\"https://picsum.photos/400/300\" />}\n>\n  <span>Hover me</span>\n</Lightbox>\n\n<Lightbox\n  trigger=\"click\"\n  position=\"center\"\n  zoomOut\n  zoomScale={0.4}\n  content={<LargeComponent />}\n  header=\"Zoomed Preview\"\n>\n  <Button>Click to preview</Button>\n</Lightbox>`;\n\nconst BasicUsage: React.FC = () => {\n    const { isDark } = useStoryTheme();\n\n    return (\n        <>\n            <ComponentDemo title=\"Lightbox Variants\" description=\"Hover and click triggers with normal and zoomed-out views.\">\n                <div className=\"flex flex-wrap gap-6 items-start\">\n                    <Lightbox\n                        trigger=\"hover\"\n                        content={\n                            <img src=\"https://picsum.photos/seed/lb1/400/300\" alt=\"Preview\" style={{ width: '100%', display: 'block' }} />\n                        }\n                        width={400}\n                        showCloseButton={false}\n                    >\n                        <div\n                            className={cn('px-4 py-3 rounded-lg border cursor-pointer transition-all', {\n                                'bg-white/5 border-white/10 hover:border-white/25': isDark,\n                                'bg-white border-gray-200 hover:border-gray-400 hover:shadow': !isDark,\n                            })}\n                        >\n                            <p className=\"text-sm font-medium\" style={{ color: 'var(--eui-text)' }}>\n                                Hover for image preview\n                            </p>\n                            <p className=\"text-xs\" style={{ color: 'var(--eui-text-muted)' }}>\n                                Image loads in a popover\n                            </p>\n                        </div>\n                    </Lightbox>\n\n                    <Lightbox\n                        trigger=\"click\"\n                        position=\"center\"\n                        content={\n                            <div className=\"p-6\" style={{ backgroundColor: 'var(--eui-bg)' }}>\n                                <h3 className=\"text-lg font-bold mb-3\" style={{ color: 'var(--eui-text)' }}>\n                                    Modal Content\n                                </h3>\n                                <p className=\"text-sm mb-4\" style={{ color: 'var(--eui-text-muted)' }}>\n                                    This opens centered like a modal. Click the backdrop or press Escape to close.\n                                </p>\n                                <img\n                                    src=\"https://picsum.photos/seed/lb2/500/300\"\n                                    alt=\"Full preview\"\n                                    style={{ width: '100%', borderRadius: '8px' }}\n                                />\n                            </div>\n                        }\n                        width={560}\n                        header=\"Image Preview\"\n                    >\n                        <Button>Click for modal preview</Button>\n                    </Lightbox>\n\n                    <Lightbox\n                        trigger=\"click\"\n                        position=\"center\"\n                        zoomOut\n                        zoomScale={0.35}\n                        zoomWidth=\"1200px\"\n                        zoomHeight=\"800px\"\n                        content={\n                            <div style={{ width: '1200px', padding: '2rem', backgroundColor: 'var(--eui-bg)' }}>\n                                <h2 className=\"text-3xl font-bold mb-4\" style={{ color: 'var(--eui-text)' }}>\n                                    Zoomed Out View\n                                </h2>\n                                <p className=\"text-lg mb-6\" style={{ color: 'var(--eui-text-muted)' }}>\n                                    This content is rendered at 1200px wide but displayed scaled down to 35%. Useful for previewing large\n                                    dashboards or complex layouts.\n                                </p>\n                                <div className=\"grid grid-cols-3 gap-4\">\n                                    {Array.from({ length: 6 }, (_, i) => (\n                                        <div\n                                            key={i}\n                                            className=\"p-4 rounded-lg border\"\n                                            style={{ borderColor: 'var(--eui-border)', backgroundColor: 'var(--eui-bg-subtle)' }}\n                                        >\n                                            <div className=\"text-xl font-bold\" style={{ color: 'var(--eui-primary)' }}>\n                                                Card {i + 1}\n                                            </div>\n                                            <p style={{ color: 'var(--eui-text-muted)' }}>\n                                                This renders at full resolution then scales down\n                                            </p>\n                                        </div>\n                                    ))}\n                                </div>\n                            </div>\n                        }\n                        width={500}\n                        height={400}\n                        header=\"Zoomed Out Preview\"\n                    >\n                        <Button variant=\"secondary\">Click for zoomed-out view</Button>\n                    </Lightbox>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default BasicUsage;\n"
        }
      ],
      "props": {
        "lightboxProps": {
          "children": {
            "type": "ReactNode",
            "required": true,
            "description": "Trigger element that opens the lightbox."
          },
          "content": {
            "type": "ReactNode",
            "required": true,
            "description": "Content to display inside the lightbox."
          },
          "trigger": {
            "type": "'hover' | 'click'",
            "default": "'hover'",
            "description": "How the lightbox is triggered."
          },
          "position": {
            "type": "'auto' | 'top' | 'bottom' | 'left' | 'right' | 'center'",
            "default": "'auto'",
            "description": "Position of the lightbox popover. Center shows as a modal."
          },
          "width": {
            "type": "string | number",
            "default": "400",
            "description": "Width of the lightbox panel."
          },
          "height": {
            "type": "string | number",
            "description": "Height of the lightbox panel."
          },
          "zoomOut": {
            "type": "boolean",
            "default": "false",
            "description": "Enable zoomed-out view mode. Content renders at full size but scaled down."
          },
          "zoomScale": {
            "type": "number",
            "default": "0.5",
            "description": "Scale factor for zoomed-out view (0.1 to 1)."
          },
          "zoomWidth": {
            "type": "string | number",
            "default": "'100vw'",
            "description": "Width of the content container in zoom-out mode."
          },
          "zoomHeight": {
            "type": "string | number",
            "default": "'100vh'",
            "description": "Height of the content container in zoom-out mode."
          },
          "backdrop": {
            "type": "boolean",
            "default": "true",
            "description": "Show backdrop overlay (center position only)."
          },
          "closeOnBackdropClick": {
            "type": "boolean",
            "default": "true",
            "description": "Close when clicking the backdrop."
          },
          "closeOnEscape": {
            "type": "boolean",
            "default": "true",
            "description": "Close on Escape key press."
          },
          "showCloseButton": {
            "type": "boolean",
            "default": "true",
            "description": "Show close button in header."
          },
          "hoverDelay": {
            "type": "number",
            "default": "300",
            "description": "Delay before opening on hover (ms)."
          },
          "hoverCloseDelay": {
            "type": "number",
            "default": "200",
            "description": "Delay before closing after mouse leaves (ms)."
          },
          "header": {
            "type": "ReactNode",
            "description": "Header content."
          },
          "footer": {
            "type": "ReactNode",
            "description": "Footer content."
          },
          "disabled": {
            "type": "boolean",
            "default": "false",
            "description": "Disable the lightbox trigger."
          },
          "onOpen": {
            "type": "() => void",
            "description": "Called when lightbox opens."
          },
          "onClose": {
            "type": "() => void",
            "description": "Called when lightbox closes."
          }
        }
      },
      "storyDir": "lightbox"
    },
    "Markdown": {
      "name": "Markdown",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React, { useState } from 'react';\nimport { MarkdownEditor } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst initial = `# Markdown Editor Showcase\n\nA **zero-dependency** editor with *full* inline and block formatting.\nInline marks: **bold**, *italic*, ***bold italic***, ~~strikethrough~~, and \\`inline code\\`.\n\n## Links and images\n\nVisit [FluxoUI on utilsware](https://fluxo-ui.utilsware.com/) — or check an autolink: <https://utilsware.com>.\n\n![Mountain landscape](https://images.unsplash.com/photo-1506905925346-21bda4d32df4?w=800 \"A mountain view\")\n\n### Lists\n\nUnordered with nesting:\n\n- First item\n- Second item\n  - Nested one\n  - Nested two\n    - Even deeper\n- Third item\n\nOrdered list:\n\n1. Wire up the toolbar\n2. Paste an image\n3. Flush uploads on submit\n\nTask list:\n\n- [x] Parser supports GFM\n- [x] Split view with mobile tabs\n- [ ] Syntax highlighting (coming soon)\n\n### Blockquote\n\n> \"Markdown should be easy to write — and even easier to read.\"\n>\n> — every documentation author ever\n\n### Fenced code\n\n\\`\\`\\`ts\nimport { MarkdownEditor } from 'fluxo-ui';\n\nconst editor = <MarkdownEditor value={md} onChange={setMd} />;\n\\`\\`\\`\n\n### Table\n\n| Feature     | Inline | Block |\n| ----------- | :----: | :---: |\n| Headings    |   —    |  yes  |\n| Images      |  yes   |  yes  |\n| Tables      |   —    |  yes  |\n| Task lists  |   —    |  yes  |\n\n---\n\nTry editing any of the above, or click the **image**, **link**, or **table** buttons in the toolbar.\n`;\n\nconst code = `import { MarkdownEditor } from 'fluxo-ui';\n\nconst [value, setValue] = useState('# Hello');\n\n<MarkdownEditor\n  value={value}\n  onChange={setValue}\n  defaultView=\"split\"\n  minHeight={420}\n/>`;\n\nconst BasicUsage: React.FC = () => {\n    const [value, setValue] = useState(initial);\n    return (\n        <>\n            <ComponentDemo title=\"Editor with Live Preview\" description=\"Edit and preview markdown with view toggling, keyboard shortcuts, and a complete toolbar.\">\n                <MarkdownEditor value={value} onChange={setValue} defaultView=\"split\" maxHeight={520} />\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "CustomToolbar",
          "code": "import React, { useState } from 'react';\nimport {\n    MarkdownEditor,\n    MINIMAL_MARKDOWN_TOOLBAR,\n    type MarkdownToolbarItem,\n} from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst customToolbar: MarkdownToolbarItem[] = [\n    'bold',\n    'italic',\n    'divider',\n    'h2',\n    'h3',\n    'divider',\n    'link',\n    'quote',\n];\n\nconst initial = `# Custom Toolbars\n\nConfigure exactly which formatting buttons appear. Pass \\`toolbar\\` with any subset of actions, or use the built-in \\`MINIMAL_MARKDOWN_TOOLBAR\\`.\n\n## Try the available formatting\n\n- **bold**, *italic*, ~~strike~~, \\`inline code\\`\n- [Link to docs](https://fluxo-ui.utilsware.com/)\n- ![Small image](https://images.unsplash.com/photo-1441974231531-c6227db76b6e?w=600)\n\n> Quotes still work even when the toolbar is hidden — all keyboard shortcuts are always available.\n\n1. Select some text\n2. Press \\`Ctrl+B\\` for bold\n3. Press \\`Ctrl+K\\` to insert a link`;\n\nconst code = `import { MarkdownEditor, MINIMAL_MARKDOWN_TOOLBAR } from 'fluxo-ui';\n\n<MarkdownEditor toolbar={MINIMAL_MARKDOWN_TOOLBAR} />\n\n<MarkdownEditor\n  toolbar={['bold', 'italic', 'divider', 'h2', 'h3', 'divider', 'link', 'quote']}\n/>\n\n<MarkdownEditor toolbar={false} />`;\n\nconst CustomToolbar: React.FC = () => {\n    const [a, setA] = useState(initial);\n    const [b, setB] = useState(initial);\n    const [c, setC] = useState(initial);\n    return (\n        <>\n            <ComponentDemo title=\"Minimal Toolbar\" description=\"Use the built-in minimal preset for simple comment boxes.\">\n                <MarkdownEditor value={a} onChange={setA} toolbar={MINIMAL_MARKDOWN_TOOLBAR} maxHeight={320} />\n            </ComponentDemo>\n            <div className=\"mt-6\">\n                <ComponentDemo title=\"Custom Selection\" description=\"Pass an explicit list of toolbar actions in your preferred order.\">\n                    <MarkdownEditor value={b} onChange={setB} toolbar={customToolbar} maxHeight={320} />\n                </ComponentDemo>\n            </div>\n            <div className=\"mt-6\">\n                <ComponentDemo title=\"No Toolbar\" description=\"Disable the toolbar entirely — keyboard shortcuts still work.\">\n                    <MarkdownEditor value={c} onChange={setC} toolbar={false} maxHeight={320} />\n                </ComponentDemo>\n            </div>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default CustomToolbar;\n"
        },
        {
          "title": "ImageUploadDeferred",
          "code": "import React, { useCallback, useRef, useState } from 'react';\nimport { MarkdownEditor, type MarkdownEditorHandle } from '../../../components';\nimport { Button } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst initial = `# Deferred Upload (Flush on Submit)\n\nDrop or paste images — they appear instantly via local \\`blob:\\` URLs.\nWhen you click **Submit**, the editor flushes all pending uploads via \\`flushUploads()\\` and replaces the blob URLs with the real ones.\n\n## Workflow\n\n1. Drop or paste any **image** into the editor\n2. Keep editing — images show up immediately\n3. Click **Submit** to run all uploads and get the final markdown\n\n![Pre-uploaded image](https://images.unsplash.com/photo-1472214103451-9374bd1c798e?w=800)\n\n> Use this strategy when you don't want to upload until the user actually commits their content.\n\n\\`\\`\\`ts\nconst final = await editorRef.current.flushUploads();\nawait api.save(final);\n\\`\\`\\`\n\n| Field     | Stored as       |\n| --------- | --------------- |\n| Drafts    | \\`blob:\\` URLs  |\n| Submitted | \\`https://\\` URL |\n`;\n\nconst code = `const editorRef = useRef<MarkdownEditorHandle>(null);\n\n<MarkdownEditor\n  ref={editorRef}\n  value={value}\n  onChange={setValue}\n  uploadStrategy=\"deferred\"\n  uploadImage={async (file) => {\n    return await myUploader(file);\n  }}\n/>\n\n<Button\n  onClick={async () => {\n    const finalMarkdown = await editorRef.current?.flushUploads();\n    submitForm(finalMarkdown);\n  }}\n>\n  Submit\n</Button>`;\n\nconst fakeUpload = async (file: File): Promise<string> => {\n    await new Promise((r) => setTimeout(r, 800));\n    return 'https://cdn.utilsware.com/uploads/' + encodeURIComponent(file.name);\n};\n\nconst ImageUploadDeferred: React.FC = () => {\n    const [value, setValue] = useState(initial);\n    const [submitted, setSubmitted] = useState<string | null>(null);\n    const [busy, setBusy] = useState(false);\n    const editorRef = useRef<MarkdownEditorHandle>(null);\n\n    const handleSubmit = useCallback(async () => {\n        if (!editorRef.current) return;\n        setBusy(true);\n        try {\n            const final = await editorRef.current.flushUploads();\n            setSubmitted(final);\n        } finally {\n            setBusy(false);\n        }\n    }, []);\n\n    return (\n        <>\n            <ComponentDemo title=\"Deferred Upload Strategy\" description=\"Images are inserted as blob URLs immediately for instant preview, then uploaded only when you flush.\">\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16 }}>\n                    <MarkdownEditor\n                        ref={editorRef}\n                        value={value}\n                        onChange={setValue}\n                        uploadStrategy=\"deferred\"\n                        uploadImage={fakeUpload}\n                        maxImageSize={5 * 1024 * 1024}\n                        maxHeight={460}\n                    />\n                    <div\n                        style={{\n                            padding: '12px 16px',\n                            background: 'var(--eui-bg-subtle)',\n                            border: '1px solid var(--eui-border-subtle)',\n                            borderRadius: 6,\n                        }}\n                    >\n                        <Button onClick={handleSubmit} disabled={busy}>\n                            {busy ? 'Uploading...' : 'Submit'}\n                        </Button>\n                    </div>\n                    {submitted && (\n                        <pre\n                            style={{\n                                margin: 0,\n                                padding: 14,\n                                background: 'var(--eui-bg-subtle)',\n                                border: '1px solid var(--eui-border-subtle)',\n                                borderRadius: 6,\n                                fontSize: 12,\n                                color: 'var(--eui-text)',\n                                whiteSpace: 'pre-wrap',\n                                overflow: 'auto',\n                                maxHeight: 240,\n                            }}\n                        >\n                            {submitted}\n                        </pre>\n                    )}\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default ImageUploadDeferred;\n"
        },
        {
          "title": "ImageUploadImmediate",
          "code": "import React, { useCallback, useState } from 'react';\nimport { MarkdownEditor } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst initial = `# Immediate Upload\n\nClick the **image** button in the toolbar, or *paste / drop* an image directly into the editor.\n\nThe editor calls your \\`uploadImage\\` callback immediately and inserts the final URL once it resolves.\n\n## Things to try\n\n1. Click the image toolbar button and choose **Upload**\n2. Paste an image from your clipboard\n3. Drag an image file from your desktop onto the editor\n\n![Existing hosted image](https://images.unsplash.com/photo-1469474968028-56623f02e42e?w=800 \"A valley at dawn\")\n\n> Already-hosted images work too — paste the URL via the **From URL** tab in the image dialog.\n\n| Action      | Works         |\n| ----------- | :-----------: |\n| Toolbar     | yes           |\n| Paste       | yes           |\n| Drag & drop | yes           |\n`;\n\nconst code = `<MarkdownEditor\n  value={value}\n  onChange={setValue}\n  uploadStrategy=\"immediate\"\n  uploadImage={async (file) => {\n    const url = await myUploader(file);\n    return url;\n  }}\n  maxImageSize={5 * 1024 * 1024}\n  acceptedImageTypes={['image/png', 'image/jpeg', 'image/webp']}\n/>`;\n\nconst fakeUpload = async (file: File): Promise<string> => {\n    await new Promise((r) => setTimeout(r, 800));\n    return URL.createObjectURL(file);\n};\n\nconst ImageUploadImmediate: React.FC = () => {\n    const [value, setValue] = useState(initial);\n    const [log, setLog] = useState<string[]>([]);\n\n    const handleUpload = useCallback(async (file: File) => {\n        setLog((prev) => [...prev, 'Uploading ' + file.name + ' (' + (file.size / 1024).toFixed(0) + ' KB)']);\n        const url = await fakeUpload(file);\n        setLog((prev) => [...prev, 'Uploaded ' + file.name]);\n        return url;\n    }, []);\n\n    return (\n        <>\n            <ComponentDemo title=\"Immediate Upload Strategy\" description=\"Every selected image uploads right away and the final URL is inserted into the markdown.\">\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16 }}>\n                    <MarkdownEditor\n                        value={value}\n                        onChange={setValue}\n                        uploadStrategy=\"immediate\"\n                        uploadImage={handleUpload}\n                        maxImageSize={5 * 1024 * 1024}\n                        acceptedImageTypes={['image/png', 'image/jpeg', 'image/webp', 'image/gif']}\n                        onUploadError={(msg) => setLog((prev) => [...prev, 'Error: ' + msg])}\n                        maxHeight={480}\n                    />\n                    {log.length > 0 && (\n                        <div\n                            style={{\n                                padding: 14,\n                                background: 'var(--eui-bg-subtle)',\n                                border: '1px solid var(--eui-border-subtle)',\n                                borderRadius: 6,\n                                fontFamily: 'ui-monospace, monospace',\n                                fontSize: 12,\n                                color: 'var(--eui-text-muted)',\n                            }}\n                        >\n                            {log.slice(-6).map((l, i) => (\n                                <div key={i}>{l}</div>\n                            ))}\n                        </div>\n                    )}\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default ImageUploadImmediate;\n"
        },
        {
          "title": "PreviewOnly",
          "code": "import React from 'react';\nimport { MarkdownPreview } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst sample = `# Preview-only Renderer\n\nUse **MarkdownPreview** when you only need to *render* markdown — comments, blog posts, or read-only docs.\n\n## What this renderer supports\n\nInline: **bold**, *italic*, ***bold italic***, ~~strike~~, \\`code\\`, and [links](https://fluxo-ui.utilsware.com/).\n\n![Ocean sunset](https://images.unsplash.com/photo-1507525428034-b723cf961d3e?w=800 \"Golden hour\")\n\n### Lists with nesting\n\n1. First top-level item\n2. Second with a nested list\n   - Nested bullet\n   - Another nested bullet\n     1. Deep ordered\n     2. Deep ordered two\n3. Third top-level item\n\n### Task list\n\n- [x] Safe URL sanitization\n- [x] Lazy-loaded images\n- [ ] Custom image resolver\n\n### Blockquote\n\n> Blockquotes can span multiple lines and contain **inline formatting**.\n>\n> They can even contain \\`code\\` and [links](https://fluxo-ui.utilsware.com/).\n\n### Fenced code block\n\n\\`\\`\\`ts\nimport { MarkdownPreview } from 'fluxo-ui';\n\n<MarkdownPreview value={markdown} openLinksInNewTab />\n\\`\\`\\`\n\n### Table with alignment\n\n| Left-aligned | Centered | Right-aligned |\n| :----------- | :------: | ------------: |\n| one          |   two    |         three |\n| short        |   long   |          text |\n| a            |    b     |             c |\n\n---\n\nUnsafe URLs like \\`javascript:alert(1)\\` are automatically blocked.\n`;\n\nconst code = `import { MarkdownPreview } from 'fluxo-ui';\n\n<MarkdownPreview value={markdown} openLinksInNewTab />`;\n\nconst PreviewOnly: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo title=\"Preview Only\" description=\"Render markdown without the editor — ideal for displaying user-generated content.\">\n                <div style={{ border: '1px solid var(--eui-border-subtle)', borderRadius: 6, background: 'var(--eui-bg)' }}>\n                    <MarkdownPreview value={sample} />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default PreviewOnly;\n"
        },
        {
          "title": "ReadOnly",
          "code": "import React from 'react';\nimport { MarkdownEditor } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst sample = `# Read-only Mode\n\nThe editor can be rendered in **read-only** mode — the textarea remains selectable, but the toolbar is disabled.\n\n## What you can see\n\nInline formatting still renders: **bold**, *italic*, ~~strike~~, \\`inline code\\`, and [links](https://fluxo-ui.utilsware.com/).\n\n![A calm lake](https://images.unsplash.com/photo-1470071459604-3b5ec3a7fe05?w=800)\n\n- Useful for displaying the editor with its chrome intact\n- Prevents any formatting changes\n- Still allows copy to clipboard\n\n1. Open this in split view\n2. Try clicking a toolbar button — it's disabled\n3. Text remains selectable so users can copy it\n\n> Read-only doesn't mean \"hidden\". It means \"visible but immutable.\"\n\n\\`\\`\\`tsx\n<MarkdownEditor value={markdown} readOnly defaultView=\"split\" />\n\\`\\`\\`\n\n| Behavior         | Read-only |\n| ---------------- | :-------: |\n| Toolbar enabled  |    no     |\n| Text selectable  |    yes    |\n| Shortcuts work   |    no     |\n| Preview updates  |    yes    |\n`;\n\nconst code = `<MarkdownEditor value={value} readOnly defaultView=\"split\" />`;\n\nconst ReadOnly: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Read-only Editor\" description=\"All toolbar actions and keyboard shortcuts are disabled.\">\n            <MarkdownEditor value={sample} readOnly defaultView=\"split\" maxHeight={420} />\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default ReadOnly;\n"
        },
        {
          "title": "ViewModes",
          "code": "import React, { useState } from 'react';\nimport { MarkdownEditor, type EditorViewMode } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst initial = `# View Modes\n\nSwitch between **Edit**, *Split*, and **Preview** from the top-right toolbar.\n\n## Sample content\n\nInline: **bold**, *italic*, ~~strike~~, \\`inline code\\`, and a [link](https://fluxo-ui.utilsware.com/).\n\n![Forest](https://images.unsplash.com/photo-1448375240586-882707db888b?w=800)\n\n- Edit-only hides the preview pane\n- Split shows both side-by-side (tabs on mobile)\n- Preview hides the editor entirely\n\n1. Try the **Edit** button\n2. Try **Split**\n3. Try **Preview**\n\n> Each view can be controlled externally via the \\`view\\` prop.\n\n\\`\\`\\`tsx\n<MarkdownEditor view={view} onViewChange={setView} />\n\\`\\`\\`\n\n| Mode    | Editor | Preview |\n| ------- | :----: | :-----: |\n| edit    |  yes   |   no    |\n| split   |  yes   |   yes   |\n| preview |   no   |   yes   |\n`;\n\nconst code = `const [view, setView] = useState<EditorViewMode>('split');\n\n<MarkdownEditor\n  value={value}\n  onChange={setValue}\n  view={view}\n  onViewChange={setView}\n/>`;\n\nconst ViewModes: React.FC = () => {\n    const [value, setValue] = useState(initial);\n    const [view, setView] = useState<EditorViewMode>('split');\n    return (\n        <>\n            <ComponentDemo title=\"Edit / Split / Preview\" description=\"Fully controlled view mode — wire it to your own UI if you want external toggles.\">\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16 }}>\n                    <MarkdownEditor value={value} onChange={setValue} view={view} onViewChange={setView} maxHeight={460} />\n                    <div\n                        style={{\n                            padding: '12px 16px',\n                            background: 'var(--eui-bg-subtle)',\n                            border: '1px solid var(--eui-border-subtle)',\n                            borderRadius: 6,\n                            fontSize: 13,\n                            color: 'var(--eui-text-muted)',\n                        }}\n                    >\n                        Current view: <strong style={{ color: 'var(--eui-text)' }}>{view}</strong>\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default ViewModes;\n"
        }
      ],
      "props": {
        "editorProps": {
          "value": {
            "type": "string",
            "description": "Controlled markdown value."
          },
          "defaultValue": {
            "type": "string",
            "description": "Initial value when uncontrolled."
          },
          "onChange": {
            "type": "(value: string) => void",
            "description": "Called whenever the markdown changes."
          },
          "placeholder": {
            "type": "string",
            "default": "'Write markdown...'",
            "description": "Placeholder shown when empty."
          },
          "readOnly": {
            "type": "boolean",
            "default": "false",
            "description": "Disable all editing while keeping the chrome."
          },
          "disabled": {
            "type": "boolean",
            "default": "false",
            "description": "Fully disable the editor."
          },
          "minHeight": {
            "type": "string | number",
            "default": "'320px'",
            "description": "Minimum height of the editor body."
          },
          "maxHeight": {
            "type": "string | number",
            "description": "Optional max height (scrolls beyond)."
          },
          "view": {
            "type": "'edit' | 'split' | 'preview'",
            "description": "Controlled view mode."
          },
          "defaultView": {
            "type": "'edit' | 'split' | 'preview'",
            "default": "'edit'",
            "description": "Initial view when uncontrolled."
          },
          "onViewChange": {
            "type": "(view: EditorViewMode) => void",
            "description": "Called when the user toggles views."
          },
          "allowedViews": {
            "type": "EditorViewMode[]",
            "description": "Restrict which view modes appear in the switcher."
          },
          "toolbar": {
            "type": "MarkdownToolbarItem[] | false",
            "default": "DEFAULT_MARKDOWN_TOOLBAR",
            "description": "Toolbar configuration or false to hide."
          },
          "showToolbar": {
            "type": "boolean",
            "default": "true",
            "description": "Hide the toolbar entirely."
          },
          "showStatusBar": {
            "type": "boolean",
            "default": "true",
            "description": "Show word/char count footer."
          },
          "showWordCount": {
            "type": "boolean",
            "default": "true",
            "description": "Toggle word count in the status bar."
          },
          "uploadImage": {
            "type": "(file: File) => Promise<string>",
            "description": "Async upload callback — must resolve with the final URL."
          },
          "uploadStrategy": {
            "type": "'immediate' | 'deferred'",
            "default": "'immediate'",
            "description": "Upload immediately on selection or defer to flushUploads()."
          },
          "maxImageSize": {
            "type": "number",
            "description": "Maximum file size in bytes."
          },
          "acceptedImageTypes": {
            "type": "string[]",
            "description": "Array of MIME types accepted for upload."
          },
          "onUploadError": {
            "type": "(message: string, file?: File) => void",
            "description": "Called when validation or upload fails."
          },
          "openLinksInNewTab": {
            "type": "boolean",
            "default": "true",
            "description": "Open preview links with target=\"_blank\"."
          },
          "spellCheck": {
            "type": "boolean",
            "default": "true",
            "description": "Enable browser spellcheck on the textarea."
          },
          "autoFocus": {
            "type": "boolean",
            "default": "false",
            "description": "Focus the editor on mount."
          },
          "ariaLabel": {
            "type": "string",
            "default": "'Markdown editor'",
            "description": "Accessible label for the textarea."
          }
        },
        "previewProps": {
          "value": {
            "type": "string",
            "description": "Markdown source to render."
          },
          "openLinksInNewTab": {
            "type": "boolean",
            "default": "true",
            "description": "Render links with target=\"_blank\" rel=\"noopener\"."
          },
          "sanitizeUrl": {
            "type": "(url: string) => string | null",
            "description": "Custom URL sanitizer — return null to block."
          },
          "imageResolver": {
            "type": "(src: string) => string",
            "description": "Rewrite image URLs before rendering."
          },
          "emptyFallback": {
            "type": "React.ReactNode",
            "description": "Shown when value is empty."
          }
        }
      },
      "storyDir": "markdown"
    },
    "MenuNav": {
      "name": "MenuNav",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React, { useState } from 'react';\nimport { MenuNav } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { basicMenuItems } from './menu-nav-story-data';\n\nconst code = `import { MenuNav } from 'fluxo-ui';\n\nconst items = [\n  { id: 'home', label: 'Home', icon: <HomeIcon /> },\n  { id: 'inbox', label: 'Inbox', icon: <InboxIcon />, badge: <Badge>5</Badge> },\n  { id: 'documents', label: 'Documents', icon: <FileIcon /> },\n  { id: 'analytics', label: 'Analytics', icon: <ChartIcon /> },\n  { id: 'users', label: 'Users', icon: <UsersIcon /> },\n  { id: 'settings', label: 'Settings', icon: <SettingsIcon /> },\n];\n\n<MenuNav\n  items={items}\n  defaultSelectedId=\"home\"\n  onSelect={(id, item) => console.log(id, item)}\n/>`;\n\nconst BasicUsage: React.FC = () => {\n    const [selectedId, setSelectedId] = useState('home');\n\n    return (\n        <>\n            <ComponentDemo title=\"Vertical Menu\" description=\"A simple vertical navigation menu with icons and a badge.\" centered={false}>\n                <div className=\"flex flex-col sm:flex-row gap-6 w-full\">\n                    <div className=\"w-full sm:w-64 shrink-0\">\n                        <MenuNav items={basicMenuItems} selectedId={selectedId} onSelect={(id) => setSelectedId(id)} />\n                    </div>\n                    <div className=\"flex-1 flex items-center justify-center text-sm opacity-60\">\n                        Selected: <strong className=\"ml-1\">{selectedId}</strong>\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "Collapsible",
          "code": "import React, { useState } from 'react';\nimport { MenuNav } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { collapsibleMenuItems } from './menu-nav-story-data';\n\nconst code = `import { MenuNav } from 'fluxo-ui';\n\nconst [collapsed, setCollapsed] = useState(false);\n\n<MenuNav\n  items={items}\n  collapsible\n  collapsed={collapsed}\n  onCollapsedChange={setCollapsed}\n  selectedId={selectedId}\n  onSelect={(id) => setSelectedId(id)}\n/>`;\n\nconst Collapsible: React.FC = () => {\n    const [selectedId, setSelectedId] = useState('home');\n    const [collapsed, setCollapsed] = useState(false);\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Collapsible Sidebar\"\n                description=\"Toggle between full and icon-only mode. Click the hamburger icon to collapse/expand.\"\n                centered={false}\n            >\n                <div className=\"flex flex-col sm:flex-row gap-6 w-full\">\n                    <div\n                        className=\"shrink-0\"\n                        style={{\n                            width: collapsed ? 'auto' : undefined,\n                            maxWidth: collapsed ? undefined : '240px',\n                            transition: 'width 0.2s ease',\n                        }}\n                    >\n                        <MenuNav\n                            items={collapsibleMenuItems}\n                            collapsible\n                            collapsed={collapsed}\n                            onCollapsedChange={setCollapsed}\n                            selectedId={selectedId}\n                            onSelect={(id) => setSelectedId(id)}\n                        />\n                    </div>\n                    <div className=\"flex-1 flex items-center justify-center text-sm opacity-60\">\n                        <div className=\"text-center\">\n                            <p>\n                                Selected: <strong>{selectedId}</strong>\n                            </p>\n                            <p className=\"mt-1\">\n                                Collapsed: <strong>{collapsed ? 'Yes' : 'No'}</strong>\n                            </p>\n                        </div>\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default Collapsible;\n"
        },
        {
          "title": "CustomSlots",
          "code": "import React, { useState } from 'react';\nimport { MenuNav } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { collapsibleMenuItems } from './menu-nav-story-data';\n\nconst code = `import { MenuNav } from 'fluxo-ui';\n\n<MenuNav\n  items={items}\n  showSearch\n  searchPlaceholder=\"Search menu...\"\n  headerSlot={\n    <div style={{ padding: '12px 16px', borderBottom: '1px solid var(--eui-border)' }}>\n      <div style={{ fontWeight: 600, fontSize: '14px' }}>Acme Inc.</div>\n      <div style={{ fontSize: '12px', opacity: 0.6 }}>Workspace</div>\n    </div>\n  }\n  footerSlot={\n    <div style={{ padding: '12px 16px', borderTop: '1px solid var(--eui-border)', display: 'flex', alignItems: 'center', gap: '8px' }}>\n      <div style={{ width: 32, height: 32, borderRadius: '50%', background: 'var(--eui-primary)', display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#fff', fontSize: '13px', fontWeight: 600 }}>JD</div>\n      <div>\n        <div style={{ fontSize: '13px', fontWeight: 500 }}>John Doe</div>\n        <div style={{ fontSize: '11px', opacity: 0.6 }}>john@acme.com</div>\n      </div>\n    </div>\n  }\n  selectedId={selectedId}\n  onSelect={(id) => setSelectedId(id)}\n/>`;\n\nconst headerSlot = (\n    <div style={{ padding: '12px 16px', borderBottom: '1px solid var(--eui-border)' }}>\n        <div style={{ fontWeight: 600, fontSize: '14px' }}>Acme Inc.</div>\n        <div style={{ fontSize: '12px', opacity: 0.6 }}>Workspace</div>\n    </div>\n);\n\nconst footerSlot = (\n    <div style={{ padding: '12px 16px', borderTop: '1px solid var(--eui-border)', display: 'flex', alignItems: 'center', gap: '8px' }}>\n        <div\n            style={{\n                width: 32,\n                height: 32,\n                borderRadius: '50%',\n                background: 'var(--eui-primary)',\n                display: 'flex',\n                alignItems: 'center',\n                justifyContent: 'center',\n                color: '#fff',\n                fontSize: '13px',\n                fontWeight: 600,\n            }}\n        >\n            JD\n        </div>\n        <div>\n            <div style={{ fontSize: '13px', fontWeight: 500 }}>John Doe</div>\n            <div style={{ fontSize: '11px', opacity: 0.6 }}>john@acme.com</div>\n        </div>\n    </div>\n);\n\nconst CustomSlots: React.FC = () => {\n    const [selectedId, setSelectedId] = useState('home');\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Header, Footer & Search\"\n                description=\"Custom header and footer slots with built-in search functionality.\"\n                centered={false}\n            >\n                <div className=\"flex flex-col sm:flex-row gap-6 w-full\">\n                    <div className=\"w-full sm:w-64 shrink-0\">\n                        <MenuNav\n                            items={collapsibleMenuItems}\n                            showSearch\n                            searchPlaceholder=\"Search menu...\"\n                            headerSlot={headerSlot}\n                            footerSlot={footerSlot}\n                            selectedId={selectedId}\n                            onSelect={(id) => setSelectedId(id)}\n                        />\n                    </div>\n                    <div className=\"flex-1 flex items-center justify-center text-sm opacity-60\">\n                        Selected: <strong className=\"ml-1\">{selectedId}</strong>\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default CustomSlots;\n"
        },
        {
          "title": "GroupedMenus",
          "code": "import React, { useState } from 'react';\nimport { MenuNav } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { groupedMenuItems } from './menu-nav-story-data';\n\nconst code = `import { MenuNav } from 'fluxo-ui';\nimport type { MenuNavGroup } from 'fluxo-ui';\n\nconst items = [\n  { id: 'home', label: 'Home', icon: <HomeIcon /> },\n  {\n    id: 'main-group',\n    label: 'Main',\n    collapsible: true,\n    defaultExpanded: true,\n    items: [\n      { id: 'inbox', label: 'Inbox', icon: <InboxIcon /> },\n      { id: 'starred', label: 'Starred', icon: <StarIcon /> },\n      { id: 'documents', label: 'Documents', icon: <FileIcon /> },\n    ],\n  },\n  {\n    id: 'analytics-group',\n    label: 'Analytics',\n    collapsible: true,\n    defaultExpanded: true,\n    items: [\n      { id: 'dashboard', label: 'Dashboard', icon: <ChartIcon /> },\n      { id: 'reports', label: 'Reports', icon: <FileIcon /> },\n    ],\n  },\n  {\n    id: 'admin-group',\n    label: 'Administration',\n    collapsible: true,\n    defaultExpanded: false,\n    items: [\n      { id: 'users', label: 'Users', icon: <UsersIcon /> },\n      { id: 'security', label: 'Security', icon: <ShieldIcon /> },\n      { id: 'settings', label: 'Settings', icon: <SettingsIcon /> },\n    ],\n  },\n];\n\n<MenuNav\n  items={items}\n  selectedId={selectedId}\n  onSelect={(id) => setSelectedId(id)}\n/>`;\n\nconst GroupedMenus: React.FC = () => {\n    const [selectedId, setSelectedId] = useState('home');\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Grouped Menu Items\"\n                description=\"Menu items organized into collapsible groups with section headers.\"\n                centered={false}\n            >\n                <div className=\"flex flex-col sm:flex-row gap-6 w-full\">\n                    <div className=\"w-full sm:w-64 shrink-0\">\n                        <MenuNav items={groupedMenuItems} selectedId={selectedId} onSelect={(id) => setSelectedId(id)} />\n                    </div>\n                    <div className=\"flex-1 flex items-center justify-center text-sm opacity-60\">\n                        Selected: <strong className=\"ml-1\">{selectedId}</strong>\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default GroupedMenus;\n"
        },
        {
          "title": "Horizontal",
          "code": "import React, { useState } from 'react';\nimport { MenuNav } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { basicMenuItems, horizontalMenuItems } from './menu-nav-story-data';\n\nconst code = `import { MenuNav } from 'fluxo-ui';\n\n<MenuNav\n  items={items}\n  orientation=\"horizontal\"\n  selectedId={selectedId}\n  onSelect={(id) => setSelectedId(id)}\n/>`;\n\nconst glowCode = `import { MenuNav } from 'fluxo-ui';\n\n<MenuNav\n  items={items}\n  orientation=\"horizontal\"\n  selectionStyle=\"glow\"\n  selectedId={selectedId}\n  onSelect={(id) => setSelectedId(id)}\n/>`;\n\nconst Horizontal: React.FC = () => {\n    const [selectedId, setSelectedId] = useState('home');\n    const [glowSelectedId, setGlowSelectedId] = useState('home');\n\n    return (\n        <>\n            <ComponentDemo title=\"Horizontal Menu\" description=\"A horizontal navigation bar with dropdown submenus.\" centered={false}>\n                <div className=\"w-full\">\n                    <MenuNav\n                        items={horizontalMenuItems}\n                        orientation=\"horizontal\"\n                        selectedId={selectedId}\n                        onSelect={(id) => setSelectedId(id)}\n                    />\n                    <div className=\"mt-4 text-sm opacity-60 text-center\">\n                        Selected: <strong>{selectedId}</strong>\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n\n            <ComponentDemo\n                title=\"Glow Pill Track\"\n                description=\"A pill-shaped track with an animated, primary-tinted glowing indicator that slides behind the active item.\"\n                centered={false}\n            >\n                <div className=\"w-full\" style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>\n                    <MenuNav\n                        items={basicMenuItems}\n                        orientation=\"horizontal\"\n                        selectionStyle=\"glow\"\n                        selectedId={glowSelectedId}\n                        onSelect={(id) => setGlowSelectedId(id)}\n                    />\n                    <div\n                        style={{\n                            padding: '12px 16px',\n                            background: 'var(--eui-bg-subtle)',\n                            border: '1px solid var(--eui-border-subtle)',\n                            borderRadius: 6,\n                            color: 'var(--eui-text-muted)',\n                        }}\n                    >\n                        Selected: <strong style={{ color: 'var(--eui-text)' }}>{glowSelectedId}</strong>\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={glowCode} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default Horizontal;\n"
        },
        {
          "title": "NestedMenus",
          "code": "import React, { useState } from 'react';\nimport { MenuNav } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { nestedMenuItems } from './menu-nav-story-data';\n\nconst code = `import { MenuNav } from 'fluxo-ui';\n\nconst items = [\n  { id: 'home', label: 'Home', icon: <HomeIcon /> },\n  {\n    id: 'settings', label: 'Settings', icon: <SettingsIcon />,\n    children: [\n      {\n        id: 'general', label: 'General',\n        children: [\n          { id: 'profile', label: 'Profile' },\n          { id: 'preferences', label: 'Preferences' },\n          {\n            id: 'notifications', label: 'Notifications',\n            children: [\n              { id: 'email-notifs', label: 'Email' },\n              { id: 'push-notifs', label: 'Push' },\n              { id: 'sms-notifs', label: 'SMS' },\n            ],\n          },\n        ],\n      },\n      {\n        id: 'security', label: 'Security',\n        children: [\n          { id: 'password', label: 'Password' },\n          { id: 'two-factor', label: 'Two-Factor Auth' },\n        ],\n      },\n    ],\n  },\n];\n\n<MenuNav\n  items={items}\n  maxSubMenuDepth={3}\n  selectedId={selectedId}\n  onSelect={(id) => setSelectedId(id)}\n/>`;\n\nconst NestedMenus: React.FC = () => {\n    const [selectedId, setSelectedId] = useState('home');\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Nested Submenus\"\n                description=\"Up to 3 levels of nested submenus with expand/collapse behavior.\"\n                centered={false}\n            >\n                <div className=\"flex flex-col sm:flex-row gap-6 w-full\">\n                    <div className=\"w-full sm:w-72 shrink-0\">\n                        <MenuNav items={nestedMenuItems} maxSubMenuDepth={3} selectedId={selectedId} onSelect={(id) => setSelectedId(id)} />\n                    </div>\n                    <div className=\"flex-1 flex items-center justify-center text-sm opacity-60\">\n                        Selected: <strong className=\"ml-1\">{selectedId}</strong>\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default NestedMenus;\n"
        },
        {
          "title": "SelectionStyles",
          "code": "import React, { useState } from 'react';\nimport type { MenuNavSelectionStyle } from '../../../components';\nimport { MenuNav } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { basicMenuItems } from './menu-nav-story-data';\n\nconst code = `import { MenuNav } from 'fluxo-ui';\nimport type { MenuNavSelectionStyle } from 'fluxo-ui';\n\n<MenuNav\n  items={items}\n  selectionStyle=\"border-left\"\n  selectedId={selectedId}\n  onSelect={(id) => setSelectedId(id)}\n/>\n\n<MenuNav\n  items={items}\n  selectionStyle=\"background\"\n  selectedId={selectedId}\n  onSelect={(id) => setSelectedId(id)}\n/>\n\n<MenuNav\n  items={items}\n  selectionStyle=\"arrow\"\n  selectedId={selectedId}\n  onSelect={(id) => setSelectedId(id)}\n/>\n\n<MenuNav\n  items={items}\n  selectionStyle=\"highlight\"\n  selectedId={selectedId}\n  onSelect={(id) => setSelectedId(id)}\n/>\n\n<MenuNav\n  items={items}\n  selectionStyle=\"glow\"\n  selectedId={selectedId}\n  onSelect={(id) => setSelectedId(id)}\n/>`;\n\nconst selectionStyles: { label: string; value: MenuNavSelectionStyle }[] = [\n    { label: 'Border Left', value: 'border-left' },\n    { label: 'Border Bottom', value: 'border-bottom' },\n    { label: 'Background', value: 'background' },\n    { label: 'Arrow', value: 'arrow' },\n    { label: 'Highlight', value: 'highlight' },\n    { label: 'Glow', value: 'glow' },\n];\n\nconst SelectionStyles: React.FC = () => {\n    const [selectedIds, setSelectedIds] = useState<Record<string, string>>({\n        'border-left': 'home',\n        'border-bottom': 'home',\n        background: 'home',\n        arrow: 'home',\n        highlight: 'home',\n        glow: 'home',\n    });\n\n    return (\n        <>\n            <ComponentDemo title=\"Selection Styles\" description=\"Six different visual styles for the selected menu item.\" centered={false}>\n                <div className=\"grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-6 w-full\">\n                    {selectionStyles.map(({ label, value }) => (\n                        <div key={value}>\n                            <p className=\"text-xs font-semibold mb-2 opacity-70\">{label}</p>\n                            <div className=\"w-full\">\n                                <MenuNav\n                                    items={basicMenuItems}\n                                    selectionStyle={value}\n                                    selectedId={selectedIds[value]}\n                                    onSelect={(id) => setSelectedIds((prev) => ({ ...prev, [value]: id }))}\n                                />\n                            </div>\n                        </div>\n                    ))}\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default SelectionStyles;\n"
        },
        {
          "title": "Sizes",
          "code": "import React, { useState } from 'react';\nimport type { MenuNavSize } from '../../../components';\nimport { MenuNav } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { basicMenuItems } from './menu-nav-story-data';\n\nconst code = `import { MenuNav } from 'fluxo-ui';\n\n<MenuNav items={items} size=\"xs\" />\n<MenuNav items={items} size=\"sm\" />\n<MenuNav items={items} size=\"md\" />\n<MenuNav items={items} size=\"lg\" />\n<MenuNav items={items} size=\"xl\" />`;\n\nconst sizes: { label: string; value: MenuNavSize }[] = [\n    { label: 'Extra Small (xs)', value: 'xs' },\n    { label: 'Small (sm)', value: 'sm' },\n    { label: 'Medium (md)', value: 'md' },\n    { label: 'Large (lg)', value: 'lg' },\n    { label: 'Extra Large (xl)', value: 'xl' },\n];\n\nconst Sizes: React.FC = () => {\n    const [selectedIds, setSelectedIds] = useState<Record<string, string>>({\n        xs: 'home',\n        sm: 'home',\n        md: 'home',\n        lg: 'home',\n        xl: 'home',\n    });\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Size Variants\"\n                description=\"The menu supports five size options from extra small to extra large.\"\n                centered={false}\n            >\n                <div className=\"grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-6 w-full\">\n                    {sizes.map(({ label, value }) => (\n                        <div key={value}>\n                            <p className=\"text-xs font-semibold mb-2 opacity-70\">{label}</p>\n                            <MenuNav\n                                items={basicMenuItems}\n                                size={value}\n                                selectedId={selectedIds[value]}\n                                onSelect={(id) => setSelectedIds((prev) => ({ ...prev, [value]: id }))}\n                            />\n                        </div>\n                    ))}\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default Sizes;\n"
        },
        {
          "title": "ToolbarMode",
          "code": "import React, { useState } from 'react';\nimport { MenuNav } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { toolbarMenuItems } from './menu-nav-story-data';\n\nconst code = `import { MenuNav } from 'fluxo-ui';\n\nconst items = [\n  { id: 'file', label: 'File', children: [\n    { id: 'new', label: 'New' },\n    { id: 'open', label: 'Open' },\n    { id: 'save', label: 'Save' },\n  ]},\n  { id: 'edit', label: 'Edit', children: [\n    { id: 'undo', label: 'Undo' },\n    { id: 'redo', label: 'Redo' },\n    { id: 'copy', label: 'Copy' },\n  ]},\n  { id: 'view', label: 'View', children: [\n    { id: 'zoom-in', label: 'Zoom In' },\n    { id: 'zoom-out', label: 'Zoom Out' },\n  ]},\n  { id: 'help', label: 'Help', children: [\n    { id: 'docs', label: 'Documentation' },\n    { id: 'about', label: 'About' },\n  ]},\n];\n\n<MenuNav\n  items={items}\n  toolbar\n  selectedId={selectedId}\n  onSelect={(id) => setSelectedId(id)}\n/>`;\n\nconst ToolbarMode: React.FC = () => {\n    const [selectedId, setSelectedId] = useState('');\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Toolbar Mode\"\n                description=\"A horizontal toolbar-style menu, typical of application menu bars.\"\n                centered={false}\n            >\n                <div className=\"w-full\">\n                    <MenuNav items={toolbarMenuItems} toolbar selectedId={selectedId} onSelect={(id) => setSelectedId(id)} />\n                    {selectedId && (\n                        <div className=\"mt-4 text-sm opacity-60 text-center\">\n                            Selected: <strong>{selectedId}</strong>\n                        </div>\n                    )}\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default ToolbarMode;\n"
        }
      ],
      "props": {
        "menuNavProps": {
          "items": {
            "type": "(MenuNavItem | MenuNavGroup)[]",
            "required": true,
            "description": "Array of menu items or groups to render."
          },
          "orientation": {
            "type": "'vertical' | 'horizontal'",
            "default": "'vertical'",
            "description": "Layout orientation of the menu."
          },
          "size": {
            "type": "'xs' | 'sm' | 'md' | 'lg' | 'xl'",
            "default": "'md'",
            "description": "Size of menu items."
          },
          "selectedId": {
            "type": "string",
            "description": "Controlled selected item ID."
          },
          "defaultSelectedId": {
            "type": "string",
            "default": "''",
            "description": "Default selected item ID for uncontrolled usage."
          },
          "onSelect": {
            "type": "(id: string, item: MenuNavItem) => void",
            "description": "Callback when a menu item is selected."
          },
          "selectionStyle": {
            "type": "'border-left' | 'border-bottom' | 'background' | 'arrow' | 'highlight' | 'glow'",
            "default": "'border-left'",
            "description": "Visual style for the selected item indicator. 'glow' renders an animated, primary-tinted glowing pill that slides behind the selected item (works in both vertical and horizontal orientations)."
          },
          "iconPosition": {
            "type": "'left' | 'right'",
            "default": "'left'",
            "description": "Position of icons relative to label text."
          },
          "collapsed": {
            "type": "boolean",
            "description": "Controlled collapsed state (icon-only mode)."
          },
          "collapsible": {
            "type": "boolean",
            "default": "false",
            "description": "Whether the menu can be collapsed to icon-only mode."
          },
          "onCollapsedChange": {
            "type": "(collapsed: boolean) => void",
            "description": "Callback when collapsed state changes."
          },
          "mobileBreakpoint": {
            "type": "number",
            "default": "768",
            "description": "Viewport width below which mobile mode activates."
          },
          "mobileFullScreen": {
            "type": "boolean",
            "default": "true",
            "description": "Whether mobile menu takes full screen."
          },
          "showSearch": {
            "type": "boolean",
            "default": "false",
            "description": "Show a search input to filter menu items."
          },
          "searchPlaceholder": {
            "type": "string",
            "default": "'Search...'",
            "description": "Placeholder text for the search input."
          },
          "searchAriaLabel": {
            "type": "string",
            "default": "'Search navigation'",
            "description": "Accessible label for the search input (used for screen readers)."
          },
          "headerSlot": {
            "type": "ReactNode",
            "description": "Custom content rendered above the menu."
          },
          "footerSlot": {
            "type": "ReactNode",
            "description": "Custom content rendered below the menu."
          },
          "maxSubMenuDepth": {
            "type": "number",
            "default": "3",
            "description": "Maximum depth of nested submenus."
          },
          "toolbar": {
            "type": "boolean",
            "default": "false",
            "description": "Enable toolbar mode (horizontal with border-bottom selection)."
          },
          "className": {
            "type": "string",
            "description": "Additional CSS class for the nav element."
          },
          "ariaLabel": {
            "type": "string",
            "default": "'Navigation'",
            "description": "ARIA label for the nav element."
          }
        }
      },
      "storyDir": "menu-nav"
    },
    "MobileTabBar": {
      "name": "MobileTabBar",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React, { useState } from 'react';\nimport { MobileTabBar } from '../../../components';\nimport { AlertIcon, DashboardIcon, SearchIcon, UserIcon } from '../../../assets/icons';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { MobileTabBar } from 'fluxo-ui';\n\nconst items = [\n    { key: 'home', label: 'Home', icon: <DashboardIcon /> },\n    { key: 'search', label: 'Search', icon: <SearchIcon /> },\n    { key: 'alerts', label: 'Alerts', icon: <AlertIcon />, badge: 3 },\n    { key: 'me', label: 'Me', icon: <UserIcon /> },\n];\n\n<MobileTabBar items={items} activeKey={tab} onChange={setTab} />`;\n\nconst items = [\n    { key: 'home', label: 'Home', icon: <DashboardIcon /> },\n    { key: 'search', label: 'Search', icon: <SearchIcon /> },\n    { key: 'alerts', label: 'Alerts', icon: <AlertIcon />, badge: 3 },\n    { key: 'me', label: 'Me', icon: <UserIcon /> },\n];\n\nconst BasicUsage: React.FC = () => {\n    const [tab, setTab] = useState('home');\n    return (\n        <>\n            <ComponentDemo title=\"Bottom tab bar\" description=\"Mounted at the bottom of a mobile app. Tap or use ←/→ arrow keys to switch tabs.\">\n                <div style={{ width: '100%', maxWidth: 380, border: '1px solid var(--eui-border-subtle)', borderRadius: 12, overflow: 'hidden' }}>\n                    <div style={{ padding: 24, minHeight: 160, background: 'var(--eui-bg-subtle)', color: 'var(--eui-text)' }}>\n                        Active tab: <strong>{tab}</strong>\n                    </div>\n                    <MobileTabBar items={items} activeKey={tab} onChange={setTab} />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\"><CodeBlock code={code} language=\"tsx\" /></div>\n        </>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "LabelModes",
          "code": "import React, { useState } from 'react';\nimport { MobileTabBar } from '../../../components';\nimport { AlertIcon, DashboardIcon, SearchIcon, UserIcon } from '../../../assets/icons';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<MobileTabBar showLabels=\"always\" items={items} ... />\n<MobileTabBar showLabels=\"active\" items={items} ... />\n<MobileTabBar showLabels=\"never\"  items={items} ... />`;\n\nconst items = [\n    { key: 'home', label: 'Home', icon: <DashboardIcon /> },\n    { key: 'search', label: 'Search', icon: <SearchIcon /> },\n    { key: 'alerts', label: 'Alerts', icon: <AlertIcon /> },\n    { key: 'me', label: 'Me', icon: <UserIcon /> },\n];\n\nconst Preview: React.FC<{ mode: 'always' | 'active' | 'never'; description: string }> = ({ mode, description }) => {\n    const [tab, setTab] = useState('home');\n    return (\n        <ComponentDemo title={`showLabels=\"${mode}\"`} description={description}>\n            <div style={{ width: '100%', maxWidth: 380, border: '1px solid var(--eui-border-subtle)', borderRadius: 12, overflow: 'hidden' }}>\n                <MobileTabBar showLabels={mode} items={items} activeKey={tab} onChange={setTab} />\n            </div>\n        </ComponentDemo>\n    );\n};\n\nconst LabelModes: React.FC = () => (\n    <>\n        <Preview mode=\"always\" description=\"All labels visible — best for first-time users.\" />\n        <div className=\"mt-4\"><Preview mode=\"active\" description=\"Only the active label — saves space while preserving context.\" /></div>\n        <div className=\"mt-4\"><Preview mode=\"never\" description=\"Icon-only — for tight bars where the icons are universally recognized.\" /></div>\n        <div className=\"mt-4\"><CodeBlock code={code} language=\"tsx\" /></div>\n    </>\n);\n\nexport default LabelModes;\n"
        },
        {
          "title": "Variants",
          "code": "import React, { useState } from 'react';\nimport { MobileTabBar } from '../../../components';\nimport type { MobileTabBarVariant } from '../../../components';\nimport { AlertIcon, DashboardIcon, SearchIcon, UserIcon } from '../../../assets/icons';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<MobileTabBar variant=\"elevated\" items={items} activeKey={tab} onChange={setTab} />`;\n\nconst items = [\n    { key: 'home', label: 'Home', icon: <DashboardIcon /> },\n    { key: 'search', label: 'Search', icon: <SearchIcon /> },\n    { key: 'alerts', label: 'Alerts', icon: <AlertIcon />, badge: 5 },\n    { key: 'me', label: 'Me', icon: <UserIcon /> },\n];\n\nconst VariantPreview: React.FC<{ variant: MobileTabBarVariant; description: string }> = ({ variant, description }) => {\n    const [tab, setTab] = useState('home');\n    return (\n        <ComponentDemo title={variant.charAt(0).toUpperCase() + variant.slice(1)} description={description}>\n            <div style={{ width: '100%', maxWidth: 380, border: '1px solid var(--eui-border-subtle)', borderRadius: 12, overflow: 'hidden', background: 'var(--eui-bg-subtle)' }}>\n                <div style={{ padding: 24, minHeight: 120 }}>&nbsp;</div>\n                <MobileTabBar variant={variant} items={items} activeKey={tab} onChange={setTab} />\n            </div>\n        </ComponentDemo>\n    );\n};\n\nconst Variants: React.FC = () => (\n    <>\n        <VariantPreview variant=\"flat\" description=\"Default — border on top, transparent bar.\" />\n        <div className=\"mt-4\"><VariantPreview variant=\"elevated\" description=\"Soft shadow above the bar (instead of a border).\" /></div>\n        <div className=\"mt-4\"><VariantPreview variant=\"pill\" description=\"Active tab gets a solid primary pill background.\" /></div>\n        <div className=\"mt-4\"><VariantPreview variant=\"floating\" description=\"Detached rounded card with shadow — modern iOS pattern.\" /></div>\n        <div className=\"mt-4\"><CodeBlock code={code} language=\"tsx\" /></div>\n    </>\n);\n\nexport default Variants;\n"
        }
      ],
      "props": {
        "mobileTabBarProps": {
          "items": {
            "type": "MobileTabBarItem[]",
            "required": true,
            "description": "Tab items. Each: { key, label, icon?, activeIcon?, badge?, disabled?, ariaLabel? }."
          },
          "activeKey": {
            "type": "string",
            "required": true,
            "description": "Key of the currently active tab."
          },
          "onChange": {
            "type": "(key: string) => void",
            "required": true,
            "description": "Called when a tab is activated."
          },
          "variant": {
            "type": "'flat' | 'elevated' | 'pill' | 'floating'",
            "default": "'flat'",
            "description": "Visual style. 'elevated' replaces the top border with a soft shadow; 'pill' fills the active item; 'floating' renders a detached rounded card."
          },
          "position": {
            "type": "'fixed' | 'sticky' | 'static'",
            "default": "'static'",
            "description": "CSS positioning of the bar."
          },
          "showLabels": {
            "type": "'always' | 'never' | 'active'",
            "default": "'always'",
            "description": "When to render the text label for each tab."
          },
          "safeArea": {
            "type": "boolean",
            "default": "true",
            "description": "Apply env(safe-area-inset-bottom) so the bar clears the iOS home indicator."
          },
          "className": {
            "type": "string",
            "description": "Additional CSS class for the bar root."
          },
          "ariaLabel": {
            "type": "string",
            "default": "'Primary'",
            "description": "Accessible name for the navigation landmark."
          }
        }
      },
      "storyDir": "mobile-tab-bar"
    },
    "Moveable": {
      "name": "Moveable",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React, { useState } from 'react';\nimport { Moveable } from '../../../components/moveable';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { Moveable } from 'fluxo-ui';\n\n<Moveable defaultPosition={{ x: 0, y: 0 }} bounds=\"parent\">\n  <div className=\"p-4 bg-bg-subtle border rounded\">Drag me</div>\n</Moveable>`;\n\nconst BasicUsage: React.FC = () => {\n    const [pos, setPos] = useState({ x: 0, y: 0 });\n\n    return (\n        <ComponentDemo\n            title=\"Basic Drag\"\n            description=\"Click and drag anywhere on the wrapped element. Tab to focus, then use arrow keys to move.\"\n        >\n            <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16 }}>\n                <div\n                    style={{\n                        position: 'relative',\n                        height: 320,\n                        background: 'var(--eui-bg-subtle)',\n                        border: '1px dashed var(--eui-border)',\n                        borderRadius: 8,\n                        overflow: 'hidden',\n                    }}\n                >\n                    <Moveable defaultPosition={{ x: 40, y: 40 }} bounds=\"parent\" onPositionChange={setPos} ariaLabel=\"Draggable card\">\n                        <div\n                            style={{\n                                padding: '14px 18px',\n                                background: 'var(--eui-bg)',\n                                border: '1px solid var(--eui-border)',\n                                borderRadius: 8,\n                                boxShadow: 'var(--eui-shadow)',\n                                color: 'var(--eui-text)',\n                                fontSize: 14,\n                                fontWeight: 500,\n                                minWidth: 140,\n                                textAlign: 'center',\n                            }}\n                        >\n                            Drag me anywhere\n                        </div>\n                    </Moveable>\n                </div>\n                <div\n                    style={{\n                        padding: '10px 14px',\n                        background: 'var(--eui-bg-subtle)',\n                        border: '1px solid var(--eui-border-subtle)',\n                        borderRadius: 6,\n                        fontSize: 12,\n                        color: 'var(--eui-text-muted)',\n                    }}\n                >\n                    Position: <strong style={{ color: 'var(--eui-text)' }}>x = {Math.round(pos.x)}, y = {Math.round(pos.y)}</strong>\n                </div>\n                <CodeBlock code={code} />\n            </div>\n        </ComponentDemo>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "GridSnap",
          "code": "import React from 'react';\nimport { Moveable } from '../../../components/moveable';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<Moveable\n  defaultPosition={{ x: 0, y: 0 }}\n  bounds=\"parent\"\n  grid={[40, 40]}\n  snapToGrid\n>\n  <div>Snaps to 40px grid</div>\n</Moveable>`;\n\nconst GridSnap: React.FC = () => (\n    <ComponentDemo\n        title=\"Grid Snap & Bounds\"\n        description=\"Drag snaps to a 40-pixel grid while staying inside the parent.\"\n    >\n        <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16 }}>\n            <div\n                style={{\n                    position: 'relative',\n                    height: 320,\n                    background:\n                        'repeating-linear-gradient(0deg, transparent 0, transparent 39px, var(--eui-border-subtle) 39px, var(--eui-border-subtle) 40px), repeating-linear-gradient(90deg, transparent 0, transparent 39px, var(--eui-border-subtle) 39px, var(--eui-border-subtle) 40px)',\n                    backgroundColor: 'var(--eui-bg-subtle)',\n                    border: '1px solid var(--eui-border)',\n                    borderRadius: 8,\n                    overflow: 'hidden',\n                }}\n            >\n                <Moveable\n                    defaultPosition={{ x: 40, y: 40 }}\n                    bounds=\"parent\"\n                    grid={[40, 40]}\n                    snapToGrid\n                    ariaLabel=\"Snaps to 40px grid\"\n                >\n                    <div\n                        style={{\n                            width: 80,\n                            height: 80,\n                            background: 'var(--eui-primary)',\n                            color: 'var(--eui-text-on-primary)',\n                            borderRadius: 6,\n                            display: 'flex',\n                            alignItems: 'center',\n                            justifyContent: 'center',\n                            fontSize: 12,\n                            fontWeight: 600,\n                        }}\n                    >\n                        Snap\n                    </div>\n                </Moveable>\n            </div>\n            <CodeBlock code={code} />\n        </div>\n    </ComponentDemo>\n);\n\nexport default GridSnap;\n"
        },
        {
          "title": "HandleAndAxis",
          "code": "import React from 'react';\nimport { Moveable } from '../../../components/moveable';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<Moveable\n  handleSelector=\".my-handle\"\n  cancelSelector=\"button\"\n  axis=\"x\"\n  bounds=\"parent\"\n>\n  <div className=\"card\">\n    <div className=\"my-handle\">::: drag here :::</div>\n    <p>Body — not draggable.</p>\n    <button>Action — clicks pass through</button>\n  </div>\n</Moveable>`;\n\nconst HandleAndAxis: React.FC = () => (\n    <ComponentDemo\n        title=\"Drag Handle & Axis Lock\"\n        description=\"Use handleSelector to restrict drag start to a header, cancelSelector to exclude inner buttons/inputs, and axis to lock to one direction.\"\n    >\n        <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16 }}>\n            <div\n                style={{\n                    position: 'relative',\n                    height: 320,\n                    background: 'var(--eui-bg-subtle)',\n                    border: '1px dashed var(--eui-border)',\n                    borderRadius: 8,\n                    overflow: 'hidden',\n                }}\n            >\n                <Moveable\n                    defaultPosition={{ x: 40, y: 40 }}\n                    bounds=\"parent\"\n                    handleSelector=\".eui-demo-handle\"\n                    cancelSelector=\"button, input\"\n                    ariaLabel=\"Card with handle\"\n                >\n                    <div\n                        style={{\n                            width: 230,\n                            background: 'var(--eui-bg)',\n                            border: '1px solid var(--eui-border)',\n                            borderRadius: 8,\n                            boxShadow: 'var(--eui-shadow)',\n                            overflow: 'hidden',\n                            color: 'var(--eui-text)',\n                        }}\n                    >\n                        <div\n                            className=\"eui-demo-handle\"\n                            style={{\n                                padding: '8px 12px',\n                                background: 'var(--eui-bg-subtle)',\n                                borderBottom: '1px solid var(--eui-border-subtle)',\n                                cursor: 'grab',\n                                fontSize: 12,\n                                fontWeight: 600,\n                                color: 'var(--eui-text-muted)',\n                            }}\n                        >\n                            ⋮⋮ Drag here\n                        </div>\n                        <div style={{ padding: 12, fontSize: 13 }}>\n                            <p style={{ margin: '0 0 8px' }}>Body text is NOT a drag handle.</p>\n                            <button\n                                type=\"button\"\n                                style={{\n                                    padding: '4px 10px',\n                                    background: 'var(--eui-primary)',\n                                    color: 'var(--eui-text-on-primary)',\n                                    border: 'none',\n                                    borderRadius: 4,\n                                    cursor: 'pointer',\n                                    fontSize: 12,\n                                }}\n                                onClick={() => alert('Click ignored by drag')}\n                            >\n                                Click me\n                            </button>\n                        </div>\n                    </div>\n                </Moveable>\n\n                <Moveable\n                    defaultPosition={{ x: 320, y: 40 }}\n                    bounds=\"parent\"\n                    axis=\"x\"\n                    ariaLabel=\"Horizontal only\"\n                >\n                    <div\n                        style={{\n                            padding: '10px 14px',\n                            background: 'linear-gradient(135deg, var(--eui-primary), var(--eui-primary-hover))',\n                            color: 'var(--eui-text-on-primary)',\n                            borderRadius: 6,\n                            fontSize: 13,\n                            fontWeight: 500,\n                        }}\n                    >\n                        axis: x only ↔\n                    </div>\n                </Moveable>\n\n                <Moveable\n                    defaultPosition={{ x: 40, y: 200 }}\n                    bounds=\"parent\"\n                    axis=\"y\"\n                    ariaLabel=\"Vertical only\"\n                >\n                    <div\n                        style={{\n                            padding: '10px 14px',\n                            background: 'linear-gradient(135deg, #10b981, #059669)',\n                            color: '#fff',\n                            borderRadius: 6,\n                            fontSize: 13,\n                            fontWeight: 500,\n                        }}\n                    >\n                        axis: y only ↕\n                    </div>\n                </Moveable>\n            </div>\n            <CodeBlock code={code} />\n        </div>\n    </ComponentDemo>\n);\n\nexport default HandleAndAxis;\n"
        },
        {
          "title": "WithResizable",
          "code": "import React from 'react';\nimport { Moveable } from '../../../components/moveable';\nimport { Resizable } from '../../../components/resizable';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `// Compose Moveable + Resizable for a floating, sizeable widget\n<Moveable defaultPosition={{ x: 24, y: 24 }} bounds=\"parent\" handleSelector=\".eui-demo-handle\">\n  <Resizable defaultWidth={260} defaultHeight={160} minWidth={140} minHeight={100}>\n    <div className=\"card\">\n      <div className=\"eui-demo-handle\">Drag</div>\n      <p>Resizable + movable</p>\n    </div>\n  </Resizable>\n</Moveable>`;\n\nconst WithResizable: React.FC = () => (\n    <ComponentDemo\n        title=\"Compose with Resizable\"\n        description=\"Wrap a Resizable inside a Moveable to get a floating panel that can be both dragged and resized — the same primitives the DashboardLayout uses.\"\n    >\n        <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16 }}>\n            <div\n                style={{\n                    position: 'relative',\n                    height: 360,\n                    background: 'var(--eui-bg-subtle)',\n                    border: '1px dashed var(--eui-border)',\n                    borderRadius: 8,\n                    overflow: 'hidden',\n                }}\n            >\n                <Moveable\n                    defaultPosition={{ x: 24, y: 24 }}\n                    bounds=\"parent\"\n                    handleSelector=\".eui-demo-handle\"\n                    cancelSelector=\"button\"\n                    ariaLabel=\"Floating panel\"\n                >\n                    <Resizable defaultWidth={260} defaultHeight={170} minWidth={160} minHeight={110} showHandles=\"hover\" ariaLabel=\"Panel body\">\n                        <div\n                            style={{\n                                width: '100%',\n                                height: '100%',\n                                background: 'var(--eui-bg)',\n                                border: '1px solid var(--eui-border)',\n                                borderRadius: 8,\n                                boxShadow: 'var(--eui-shadow)',\n                                display: 'flex',\n                                flexDirection: 'column',\n                                overflow: 'hidden',\n                                color: 'var(--eui-text)',\n                            }}\n                        >\n                            <div\n                                className=\"eui-demo-handle\"\n                                style={{\n                                    padding: '8px 12px',\n                                    background: 'var(--eui-bg-subtle)',\n                                    borderBottom: '1px solid var(--eui-border-subtle)',\n                                    cursor: 'grab',\n                                    fontWeight: 600,\n                                    fontSize: 12,\n                                    color: 'var(--eui-text-muted)',\n                                    flexShrink: 0,\n                                }}\n                            >\n                                ⋮⋮ Floating Panel\n                            </div>\n                            <div style={{ padding: 12, fontSize: 13, flex: 1, overflow: 'auto' }}>\n                                Drag the title bar to move. Drag the bottom-right corner to resize.\n                            </div>\n                        </div>\n                    </Resizable>\n                </Moveable>\n            </div>\n            <CodeBlock code={code} />\n        </div>\n    </ComponentDemo>\n);\n\nexport default WithResizable;\n"
        }
      ],
      "props": {
        "moveableProps": {
          "children": {
            "type": "React.ReactNode",
            "required": true,
            "description": "Element(s) wrapped by the movable container."
          },
          "defaultPosition": {
            "type": "{ x: number; y: number }",
            "default": "{ x: 0, y: 0 }",
            "description": "Initial position (uncontrolled). Translated relative to the wrapper's CSS origin."
          },
          "position": {
            "type": "{ x: number; y: number }",
            "description": "Controlled position. Provide together with `onPositionChange`."
          },
          "onPositionChange": {
            "type": "(pos: { x: number; y: number }) => void",
            "description": "Fires on every position change (mouse, touch, keyboard)."
          },
          "onMoveStart": {
            "type": "(event: MoveableStartEvent) => void",
            "description": "Fires when a drag/keypress sequence begins."
          },
          "onMove": {
            "type": "(event: MoveableMoveEvent) => void",
            "description": "Fires continuously while moving."
          },
          "onMoveEnd": {
            "type": "(event: MoveableEndEvent) => void",
            "description": "Fires when the move gesture ends."
          },
          "axis": {
            "type": "'both' | 'x' | 'y'",
            "default": "'both'",
            "description": "Restrict movement to a single axis."
          },
          "bounds": {
            "type": "'parent' | 'window' | 'none' | { left, top, right, bottom }",
            "default": "'none'",
            "description": "Confine movement. Numeric bounds are translate-space offsets (not CSS coords)."
          },
          "grid": {
            "type": "[number, number]",
            "description": "Snap position to a [stepX, stepY] grid (requires `snapToGrid`)."
          },
          "disabled": {
            "type": "boolean",
            "default": "false",
            "description": "Disable all interaction."
          },
          "handleSelector": {
            "type": "string",
            "description": "CSS selector for an inner handle. If set, drags only start when the pointer is on a matching element."
          },
          "cancelSelector": {
            "type": "string",
            "description": "CSS selector for inner elements that should NOT initiate drag (buttons, inputs, etc.)."
          },
          "cursor": {
            "type": "string",
            "default": "'move'",
            "description": "Cursor used while dragging."
          },
          "snapToGrid": {
            "type": "boolean",
            "default": "true",
            "description": "Apply the `grid` snap. Ignored if `grid` is unset."
          },
          "keyboardStep": {
            "type": "number",
            "default": "8",
            "description": "Pixels per arrow-key press when the wrapper is focused."
          },
          "keyboardBigStep": {
            "type": "number",
            "default": "32",
            "description": "Pixels per Shift+arrow press."
          },
          "elevateOnDrag": {
            "type": "boolean",
            "default": "true",
            "description": "Add `z-index` + shadow while dragging."
          },
          "rememberLastPosition": {
            "type": "boolean",
            "default": "false",
            "description": "Persist the last position to `localStorage` (requires `storageKey`)."
          },
          "storageKey": {
            "type": "string",
            "description": "localStorage key for `rememberLastPosition`."
          },
          "className": {
            "type": "string",
            "description": "Class name applied to the outer wrapper."
          },
          "style": {
            "type": "React.CSSProperties",
            "description": "Inline styles for the wrapper."
          },
          "ariaLabel": {
            "type": "string",
            "default": "'Movable element'",
            "description": "Accessible name for the draggable wrapper."
          }
        }
      },
      "storyDir": "moveable"
    },
    "NavBar": {
      "name": "NavBar",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React, { useState } from 'react';\nimport { NavBar, Button } from '../../../components';\nimport { SearchIcon, SettingsIcon } from '../../../assets/icons';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { NavBar, Button } from 'fluxo-ui';\n\n<NavBar\n    title=\"Inbox\"\n    subtitle=\"3 unread\"\n    onBack={goBack}\n    actions={(\n        <>\n            <Button leftIcon={SearchIcon} ariaLabel=\"Search\" layout=\"plain\" />\n            <Button leftIcon={SettingsIcon} ariaLabel=\"Settings\" layout=\"plain\" />\n        </>\n    )}\n/>`;\n\nconst phoneFrame: React.CSSProperties = {\n    width: '100%',\n    maxWidth: 380,\n    border: '1px solid var(--eui-border-subtle)',\n    borderRadius: 12,\n    overflow: 'hidden',\n    background: 'var(--eui-bg-subtle)',\n};\n\nconst BasicUsage: React.FC = () => {\n    const [pings, setPings] = useState(0);\n    return (\n        <>\n            <ComponentDemo title=\"Standard mobile nav bar\" description=\"Back button on the left, title in the middle, action icons on the right.\">\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16, alignItems: 'center' }}>\n                    <div style={phoneFrame}>\n                        <NavBar\n                            title=\"Inbox\"\n                            subtitle=\"3 unread\"\n                            onBack={() => setPings((n) => n + 1)}\n                            actions={(\n                                <>\n                                    <Button leftIcon={SearchIcon} ariaLabel=\"Search\" layout=\"plain\" />\n                                    <Button leftIcon={SettingsIcon} ariaLabel=\"Settings\" layout=\"plain\" />\n                                </>\n                            )}\n                        />\n                        <div style={{ padding: 16, minHeight: 80, color: 'var(--eui-text-muted)' }}>\n                            Page body content goes here.\n                        </div>\n                    </div>\n                    <div style={{ padding: '10px 14px', background: 'var(--eui-bg-subtle)', border: '1px solid var(--eui-border-subtle)', borderRadius: 6, fontSize: 12, color: 'var(--eui-text-muted)' }}>\n                        Back-button taps: <strong style={{ color: 'var(--eui-text)' }}>{pings}</strong>\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\"><CodeBlock code={code} language=\"tsx\" /></div>\n        </>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "Variants",
          "code": "import React from 'react';\nimport { NavBar, Button } from '../../../components';\nimport { MenuIcon, SearchIcon, SettingsIcon } from '../../../assets/icons';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<NavBar variant=\"standard\" title=\"Standard\" actions={...} onBack={...} />\n<NavBar variant=\"centered\" title=\"Centered\" actions={...} onBack={...} />\n<NavBar variant=\"large\" title=\"Large title\" actions={...} />\n<NavBar variant=\"compact\" title=\"Compact\" actions={...} onBack={...} />`;\n\nconst frame: React.CSSProperties = {\n    width: '100%',\n    maxWidth: 380,\n    border: '1px solid var(--eui-border-subtle)',\n    borderRadius: 12,\n    overflow: 'hidden',\n    background: 'var(--eui-bg-subtle)',\n};\n\nconst body = (\n    <div style={{ padding: 16, minHeight: 80, color: 'var(--eui-text-muted)' }}>Body content</div>\n);\n\nconst actions = (\n    <>\n        <Button leftIcon={SearchIcon} ariaLabel=\"Search\" layout=\"plain\" />\n        <Button leftIcon={SettingsIcon} ariaLabel=\"Settings\" layout=\"plain\" />\n    </>\n);\n\nconst Variants: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Standard\" description=\"Title sits next to the leading area — default layout.\">\n            <div style={frame}>\n                <NavBar variant=\"standard\" title=\"Settings\" onBack={() => undefined} actions={actions} />\n                {body}\n            </div>\n        </ComponentDemo>\n\n        <ComponentDemo title=\"Centered\" description=\"Title is absolutely centered between leading and actions — iOS-style.\" className=\"mt-4\">\n            <div style={frame}>\n                <NavBar variant=\"centered\" title=\"Inbox\" onBack={() => undefined} actions={actions} />\n                {body}\n            </div>\n        </ComponentDemo>\n\n        <ComponentDemo title=\"Large title\" description=\"iOS-style large title rendered on its own row below the toolbar.\" className=\"mt-4\">\n            <div style={frame}>\n                <NavBar variant=\"large\" title=\"Library\" subtitle=\"42 items\" actions={actions} leading={<Button leftIcon={MenuIcon} ariaLabel=\"Menu\" layout=\"plain\" />} />\n                {body}\n            </div>\n        </ComponentDemo>\n\n        <ComponentDemo title=\"Compact\" description=\"Slim toolbar — pairs well with embedded screens or dense layouts.\" className=\"mt-4\">\n            <div style={frame}>\n                <NavBar variant=\"compact\" title=\"Filters\" onBack={() => undefined} actions={actions} />\n                {body}\n            </div>\n        </ComponentDemo>\n\n        <ComponentDemo title=\"Transparent\" description=\"Use over hero imagery — drop background and border.\" className=\"mt-4\">\n            <div style={{ ...frame, background: 'linear-gradient(135deg, #2563eb, #06b6d4)' }}>\n                <NavBar variant=\"transparent\" title={<span style={{ color: '#fff' }}>Photo</span>} onBack={() => undefined} bordered={false} actions={(<Button leftIcon={SettingsIcon} ariaLabel=\"Settings\" layout=\"plain\" />)} />\n                <div style={{ padding: 16, minHeight: 80, color: '#fff' }}>Hero image…</div>\n            </div>\n        </ComponentDemo>\n\n        <div className=\"mt-4\"><CodeBlock code={code} language=\"tsx\" /></div>\n    </>\n);\n\nexport default Variants;\n"
        },
        {
          "title": "WithExtras",
          "code": "import React, { useState } from 'react';\nimport { NavBar, SelectButton, TextInput } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<NavBar\n    title=\"Library\"\n    onBack={goBack}\n>\n    <SelectButton variant=\"segmented\" items={...} value={view} onChange={...} />\n</NavBar>`;\n\nconst frame: React.CSSProperties = {\n    width: '100%',\n    maxWidth: 380,\n    border: '1px solid var(--eui-border-subtle)',\n    borderRadius: 12,\n    overflow: 'hidden',\n    background: 'var(--eui-bg-subtle)',\n};\n\nconst WithExtras: React.FC = () => {\n    const [view, setView] = useState<string>('all');\n    const [q, setQ] = useState('');\n    return (\n        <>\n            <ComponentDemo title=\"With segmented sub-row\" description=\"Pass children to render an extra row below the toolbar — handy for segmented filters or tabs.\">\n                <div style={frame}>\n                    <NavBar title=\"Library\" onBack={() => undefined}>\n                        <SelectButton\n                            variant=\"segmented\"\n                            fullWidth\n                            items={[\n                                { value: 'all', label: 'All' },\n                                { value: 'pinned', label: 'Pinned' },\n                                { value: 'recent', label: 'Recent' },\n                            ]}\n                            value={view}\n                            onChange={(e) => setView(e.value as string)}\n                        />\n                    </NavBar>\n                    <div style={{ padding: 16, minHeight: 80, color: 'var(--eui-text-muted)' }}>Showing: <strong style={{ color: 'var(--eui-text)' }}>{view}</strong></div>\n                </div>\n            </ComponentDemo>\n\n            <ComponentDemo title=\"With search sub-row\" description=\"Place a TextInput in children for an inline search experience.\" className=\"mt-4\">\n                <div style={frame}>\n                    <NavBar title=\"Search\">\n                        <TextInput value={q} onChange={(e) => setQ(e.value)} placeholder=\"Search messages…\" />\n                    </NavBar>\n                    <div style={{ padding: 16, minHeight: 80, color: 'var(--eui-text-muted)' }}>Query: <strong style={{ color: 'var(--eui-text)' }}>{q || '—'}</strong></div>\n                </div>\n            </ComponentDemo>\n\n            <div className=\"mt-4\"><CodeBlock code={code} language=\"tsx\" /></div>\n        </>\n    );\n};\n\nexport default WithExtras;\n"
        }
      ],
      "props": {
        "navBarProps": {
          "title": {
            "type": "ReactNode",
            "description": "Main title rendered in the bar (or as a large title when variant='large')."
          },
          "subtitle": {
            "type": "ReactNode",
            "description": "Optional secondary line below the title."
          },
          "leading": {
            "type": "ReactNode",
            "description": "Element placed at the start of the bar after the back button (e.g., logo, avatar, menu icon)."
          },
          "actions": {
            "type": "ReactNode",
            "description": "Right-aligned action group (icons, buttons, menus)."
          },
          "onBack": {
            "type": "() => void",
            "description": "Click handler for the back button. When provided, the back button is shown automatically."
          },
          "backLabel": {
            "type": "string",
            "default": "'Back'",
            "description": "Accessible/text label for the back button. Hidden visually on screens below the small breakpoint."
          },
          "showBack": {
            "type": "boolean",
            "description": "Force showing/hiding the back button. Defaults to true when onBack is set."
          },
          "variant": {
            "type": "'standard' | 'centered' | 'large' | 'transparent' | 'compact'",
            "default": "'standard'",
            "description": "Visual layout. 'centered' centers the title between leading/actions (iOS-style). 'large' renders an iOS-style large title that collapses on scroll. 'transparent' removes background and border. 'compact' is a slim toolbar."
          },
          "position": {
            "type": "'top' | 'sticky' | 'fixed' | 'static'",
            "default": "'static'",
            "description": "Page positioning of the bar."
          },
          "bordered": {
            "type": "boolean",
            "default": "true",
            "description": "Show a thin border under the bar."
          },
          "elevated": {
            "type": "boolean",
            "default": "false",
            "description": "Replace the bottom border with a soft drop shadow."
          },
          "safeArea": {
            "type": "boolean",
            "default": "false",
            "description": "Apply env(safe-area-inset-*) padding so the bar respects iOS notches and home indicator."
          },
          "collapseOnScroll": {
            "type": "boolean",
            "default": "false",
            "description": "When variant='large', shrink the large title into the inline row as the page scrolls."
          },
          "scrollContainer": {
            "type": "HTMLElement | null",
            "description": "Scrollable element to observe for collapseOnScroll. Defaults to window."
          },
          "children": {
            "type": "ReactNode",
            "description": "Optional extra row rendered below the toolbar (e.g., a search input, segmented control, tabs)."
          },
          "className": {
            "type": "string",
            "description": "Additional CSS class for the bar root."
          },
          "ariaLabel": {
            "type": "string",
            "description": "Accessible name applied to the landmark <header>."
          }
        }
      },
      "storyDir": "nav-bar"
    },
    "NotificationCenter": {
      "name": "NotificationCenter",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React, { useState } from 'react';\nimport type { NotificationItem } from '../../../components';\nimport { NotificationCenter } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst now = Date.now();\nconst initialItems: NotificationItem[] = [\n    {\n        id: '1',\n        title: 'New message from Alice',\n        description: 'Hey, can you review the latest PR?',\n        timestamp: new Date(now - 2 * 60 * 1000),\n        read: false,\n    },\n    {\n        id: '2',\n        title: 'Build succeeded',\n        description: 'Production deployment completed.',\n        timestamp: new Date(now - 15 * 60 * 1000),\n        read: false,\n    },\n    {\n        id: '3',\n        title: 'Comment on issue #42',\n        description: 'Bob mentioned you in a comment.',\n        timestamp: new Date(now - 60 * 60 * 1000),\n        read: true,\n    },\n    {\n        id: '4',\n        title: 'New team member',\n        description: 'Charlie joined the development team.',\n        timestamp: new Date(now - 3 * 60 * 60 * 1000),\n        read: true,\n    },\n    {\n        id: '5',\n        title: 'System update',\n        description: 'Scheduled maintenance tonight at 10 PM.',\n        timestamp: new Date(now - 24 * 60 * 60 * 1000),\n        read: true,\n    },\n];\n\nconst code = `import { NotificationCenter } from 'fluxo-ui';\nimport type { NotificationItem } from 'fluxo-ui';\n\nconst [items, setItems] = useState<NotificationItem[]>([...]);\n\n<NotificationCenter\n  items={items}\n  onItemClick={(item) => console.log('Clicked:', item.title)}\n  onMarkRead={(id) => markAsRead(id)}\n  onMarkAllRead={() => markAllRead()}\n  onClear={() => setItems([])}\n/>`;\n\nconst BasicUsage: React.FC = () => {\n    const [items, setItems] = useState(initialItems);\n\n    const handleMarkRead = (id: string) => {\n        setItems((prev) => prev.map((item) => (item.id === id ? { ...item, read: true } : item)));\n    };\n\n    const handleMarkAllRead = () => {\n        setItems((prev) => prev.map((item) => ({ ...item, read: true })));\n    };\n\n    const handleClear = () => {\n        setItems([]);\n    };\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Notification Bell\"\n                description=\"Click the bell icon to open the notification panel. Unread count is shown as a badge.\"\n            >\n                <NotificationCenter\n                    items={items}\n                    onItemClick={(item) => console.log('Clicked:', item.title)}\n                    onMarkRead={handleMarkRead}\n                    onMarkAllRead={handleMarkAllRead}\n                    onClear={handleClear}\n                />\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "Categories",
          "code": "import React, { useState } from 'react';\nimport type { NotificationItem } from '../../../components';\nimport { NotificationCenter } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst now = Date.now();\nconst initialItems: NotificationItem[] = [\n    {\n        id: '1',\n        title: 'Pull request approved',\n        description: 'Your PR #78 was approved by 2 reviewers.',\n        timestamp: new Date(now - 5 * 60 * 1000),\n        read: false,\n        category: 'Updates',\n    },\n    {\n        id: '2',\n        title: 'New follower',\n        description: 'Dave started following you.',\n        timestamp: new Date(now - 10 * 60 * 1000),\n        read: false,\n        category: 'Social',\n    },\n    {\n        id: '3',\n        title: 'Security alert',\n        description: 'New login detected from Chrome on Windows.',\n        timestamp: new Date(now - 30 * 60 * 1000),\n        read: false,\n        category: 'Alerts',\n    },\n    {\n        id: '4',\n        title: 'Task assigned',\n        description: 'You were assigned to \"Fix login bug\".',\n        timestamp: new Date(now - 60 * 60 * 1000),\n        read: true,\n        category: 'Updates',\n    },\n    {\n        id: '5',\n        title: 'Friend request',\n        description: 'Eve sent you a connection request.',\n        timestamp: new Date(now - 2 * 60 * 60 * 1000),\n        read: true,\n        category: 'Social',\n    },\n    {\n        id: '6',\n        title: 'Payment failed',\n        description: 'Your subscription payment was declined.',\n        timestamp: new Date(now - 4 * 60 * 60 * 1000),\n        read: false,\n        category: 'Alerts',\n    },\n    {\n        id: '7',\n        title: 'Code review requested',\n        description: 'Review changes in feat/new-api branch.',\n        timestamp: new Date(now - 24 * 60 * 60 * 1000),\n        read: true,\n        category: 'Updates',\n    },\n];\n\nconst code = `import { NotificationCenter } from 'fluxo-ui';\n\n<NotificationCenter\n  items={items}\n  categories={['Updates', 'Social', 'Alerts']}\n  onItemClick={(item) => console.log(item)}\n  onMarkRead={(id) => markAsRead(id)}\n  onMarkAllRead={() => markAllRead()}\n/>`;\n\nconst Categories: React.FC = () => {\n    const [items, setItems] = useState(initialItems);\n\n    const handleMarkRead = (id: string) => {\n        setItems((prev) => prev.map((item) => (item.id === id ? { ...item, read: true } : item)));\n    };\n\n    const handleMarkAllRead = () => {\n        setItems((prev) => prev.map((item) => ({ ...item, read: true })));\n    };\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Category Tabs\"\n                description=\"Filter notifications by category using tab buttons. The 'All' tab shows everything.\"\n            >\n                <NotificationCenter\n                    items={items}\n                    categories={['Updates', 'Social', 'Alerts']}\n                    onItemClick={(item) => console.log('Clicked:', item.title)}\n                    onMarkRead={handleMarkRead}\n                    onMarkAllRead={handleMarkAllRead}\n                />\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default Categories;\n"
        },
        {
          "title": "CustomTrigger",
          "code": "import React, { useState } from 'react';\nimport type { NotificationItem } from '../../../components';\nimport { Button, NotificationCenter } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst now = Date.now();\nconst items: NotificationItem[] = [\n    {\n        id: '1',\n        title: 'Welcome!',\n        description: 'Thanks for trying the custom trigger demo.',\n        timestamp: new Date(now - 10 * 1000),\n        read: false,\n    },\n    {\n        id: '2',\n        title: 'Feature released',\n        description: 'Dark mode is now available.',\n        timestamp: new Date(now - 60 * 60 * 1000),\n        read: true,\n    },\n];\n\nconst code = `import { NotificationCenter, Button } from 'fluxo-ui';\n\n<NotificationCenter\n  items={items}\n  triggerElement={<Button variant=\"primary\" size=\"sm\">Notifications</Button>}\n  header={<div className=\"p-3 font-bold text-lg\">My Alerts</div>}\n  footer={<div className=\"p-3 text-center text-sm\">View all notifications</div>}\n  width=\"420px\"\n  maxHeight=\"300px\"\n/>`;\n\nconst CustomTrigger: React.FC = () => {\n    const [notifs, setNotifs] = useState(items);\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Custom Trigger & Layout\"\n                description=\"Replace the default bell icon with any element. Customize header, footer, width, and max height.\"\n            >\n                <NotificationCenter\n                    items={notifs}\n                    triggerElement={\n                        <Button variant=\"primary\" size=\"sm\">\n                            Notifications ({notifs.filter((n) => !n.read).length})\n                        </Button>\n                    }\n                    header={\n                        <div\n                            className=\"p-3 flex items-center justify-between\"\n                            style={{ borderBottom: '1px solid var(--eui-border-subtle)' }}\n                        >\n                            <span className=\"font-bold text-lg\" style={{ color: 'var(--eui-text)' }}>\n                                My Alerts\n                            </span>\n                        </div>\n                    }\n                    footer={\n                        <div\n                            className=\"p-3 text-center text-sm cursor-pointer\"\n                            style={{ color: 'var(--eui-text-muted)', borderTop: '1px solid var(--eui-border-subtle)' }}\n                        >\n                            View all notifications\n                        </div>\n                    }\n                    width=\"420px\"\n                    maxHeight=\"300px\"\n                    onItemClick={(item) => console.log('Clicked:', item.title)}\n                    onMarkRead={(id) => setNotifs((prev) => prev.map((n) => (n.id === id ? { ...n, read: true } : n)))}\n                />\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default CustomTrigger;\n"
        }
      ],
      "props": {
        "notificationCenterProps": {
          "items": {
            "type": "NotificationItem[]",
            "required": true,
            "description": "Array of notification items."
          },
          "categories": {
            "type": "string[]",
            "description": "Category names for tab filtering."
          },
          "unreadCount": {
            "type": "number",
            "description": "Override the auto-computed unread badge count."
          },
          "onItemClick": {
            "type": "(item: NotificationItem) => void",
            "description": "Called when a notification is clicked."
          },
          "onMarkRead": {
            "type": "(id: string) => void",
            "description": "Called when marking a single notification as read."
          },
          "onMarkAllRead": {
            "type": "() => void",
            "description": "Called when \"Mark all read\" is clicked."
          },
          "onClear": {
            "type": "() => void",
            "description": "Called when \"Clear all\" is clicked."
          },
          "onLoadMore": {
            "type": "() => Promise<void>",
            "description": "Called when scrolling near the bottom to load more."
          },
          "hasMore": {
            "type": "boolean",
            "default": "false",
            "description": "Whether more notifications can be loaded."
          },
          "isLoading": {
            "type": "boolean",
            "default": "false",
            "description": "Show loading indicator at the bottom."
          },
          "triggerElement": {
            "type": "ReactNode",
            "description": "Custom trigger element (replaces the default bell icon)."
          },
          "emptyMessage": {
            "type": "ReactNode",
            "default": "'No notifications'",
            "description": "Message shown when the list is empty."
          },
          "header": {
            "type": "ReactNode",
            "description": "Custom header for the notification panel."
          },
          "footer": {
            "type": "ReactNode",
            "description": "Custom footer for the notification panel."
          },
          "width": {
            "type": "string",
            "default": "'380px'",
            "description": "Width of the notification panel."
          },
          "maxHeight": {
            "type": "string",
            "default": "'480px'",
            "description": "Maximum height of the scrollable list."
          },
          "itemTemplate": {
            "type": "(item: NotificationItem) => ReactNode",
            "description": "Custom render function for notification items."
          },
          "className": {
            "type": "string",
            "description": "Additional CSS class for the panel."
          }
        },
        "itemProps": {
          "id": {
            "type": "string",
            "required": true,
            "description": "Unique identifier."
          },
          "title": {
            "type": "string",
            "required": true,
            "description": "Notification title."
          },
          "description": {
            "type": "string",
            "description": "Notification description text."
          },
          "timestamp": {
            "type": "string | Date",
            "description": "When the notification occurred."
          },
          "icon": {
            "type": "ReactNode",
            "description": "Icon displayed on the left."
          },
          "read": {
            "type": "boolean",
            "description": "Whether the notification has been read."
          },
          "category": {
            "type": "string",
            "description": "Category for tab filtering."
          },
          "action": {
            "type": "ReactNode",
            "description": "Action button or link for the notification."
          },
          "data": {
            "type": "Record<string, unknown>",
            "description": "Custom data attached to the notification."
          }
        }
      },
      "storyDir": "notification-center"
    },
    "PageBanner": {
      "name": "PageBanner",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React from 'react';\nimport { PageBanner } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { PageBanner } from 'fluxo-ui';\n\n<PageBanner type=\"info\" message=\"This is an informational banner.\" />\n<PageBanner type=\"success\" message=\"Operation completed successfully!\" />\n<PageBanner type=\"warning\" message=\"Please review before proceeding.\" />\n<PageBanner type=\"error\" message=\"Something went wrong. Please try again.\" />\n<PageBanner type=\"default\" message=\"This is a default banner.\" />`;\n\nconst BasicUsage: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo title=\"Banner Types\" description=\"PageBanner supports five types: info, success, warning, error, and default.\">\n                <div className=\"space-y-4\">\n                    <PageBanner\n                        type=\"info\"\n                        message=\"This is an informational banner with helpful context for the user.\"\n                        dismissible={false}\n                    />\n                    <PageBanner\n                        type=\"success\"\n                        message=\"Operation completed successfully! Your changes have been saved.\"\n                        dismissible={false}\n                    />\n                    <PageBanner\n                        type=\"warning\"\n                        message=\"Please review your input before proceeding. Some fields may need attention.\"\n                        dismissible={false}\n                    />\n                    <PageBanner\n                        type=\"error\"\n                        message=\"Something went wrong while processing your request. Please try again.\"\n                        dismissible={false}\n                    />\n                    <PageBanner type=\"default\" message=\"This is a default banner for general-purpose messaging.\" dismissible={false} />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "CustomContent",
          "code": "import React from 'react';\nimport { PageBanner } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { PageBanner } from 'fluxo-ui';\n\n<PageBanner\n  type=\"info\"\n  title=\"Custom Title\"\n  message={<span>Rich <strong>HTML</strong> content in the message.</span>}\n  icon={<CustomIcon />}\n/>\n\n<PageBanner\n  type=\"success\"\n  message=\"Banner without an icon.\"\n  showIcon={false}\n/>`;\n\nconst rocketIcon = (\n    <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n        <path d=\"M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.7-2.13-.09-2.91a2.18 2.18 0 00-2.91-.09z\" />\n        <path d=\"M12 15l-3-3a22 22 0 012-3.95A12.88 12.88 0 0122 2c0 2.72-.78 7.5-6 11a22.35 22.35 0 01-4 2z\" />\n        <path d=\"M9 12H4s.55-3.03 2-4c1.62-1.08 5 0 5 0\" />\n        <path d=\"M12 15v5s3.03-.55 4-2c1.08-1.62 0-5 0-5\" />\n    </svg>\n);\n\nconst shieldIcon = (\n    <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n        <path d=\"M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z\" />\n        <path d=\"M9 12l2 2 4-4\" />\n    </svg>\n);\n\nconst bellIcon = (\n    <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n        <path d=\"M18 8A6 6 0 006 8c0 7-3 9-3 9h18s-3-2-3-9\" />\n        <path d=\"M13.73 21a2 2 0 01-3.46 0\" />\n    </svg>\n);\n\nconst CustomContent: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo\n                title=\"Custom Icons\"\n                description=\"Provide a custom icon via the icon prop to replace the default type-based icon.\"\n            >\n                <div className=\"space-y-4\">\n                    <PageBanner\n                        type=\"info\"\n                        title=\"New Feature Available\"\n                        message=\"We just launched a brand-new dashboard with real-time analytics. Check it out!\"\n                        icon={rocketIcon}\n                        dismissible={false}\n                    />\n                    <PageBanner\n                        type=\"success\"\n                        title=\"Security Verified\"\n                        message=\"Your account has been verified and all security checks have passed.\"\n                        icon={shieldIcon}\n                        dismissible={false}\n                    />\n                    <PageBanner\n                        type=\"warning\"\n                        title=\"Reminder\"\n                        message=\"You have 3 unread notifications waiting for your attention.\"\n                        icon={bellIcon}\n                        dismissible={false}\n                    />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n\n            <ComponentDemo title=\"Rich Message Content\" description=\"The message prop accepts ReactNode, allowing rich HTML content.\">\n                <div className=\"space-y-4\">\n                    <PageBanner\n                        type=\"info\"\n                        title=\"Scheduled Maintenance\"\n                        message={\n                            <span>\n                                Our servers will undergo maintenance on <strong>April 15, 2026</strong> from\n                                <strong> 2:00 AM</strong> to <strong>4:00 AM UTC</strong>. Please save your work beforehand.\n                            </span>\n                        }\n                        dismissible={false}\n                    />\n                    <PageBanner\n                        type=\"error\"\n                        message={\n                            <span>\n                                Failed to connect to the database. Please check your{' '}\n                                <a href=\"#\" className=\"underline font-semibold\">\n                                    connection settings\n                                </a>{' '}\n                                or contact{' '}\n                                <a href=\"#\" className=\"underline font-semibold\">\n                                    support\n                                </a>\n                                .\n                            </span>\n                        }\n                        dismissible={false}\n                    />\n                </div>\n            </ComponentDemo>\n\n            <ComponentDemo title=\"Without Icon\" description=\"Set showIcon to false to hide the icon entirely.\">\n                <div className=\"space-y-4\">\n                    <PageBanner type=\"default\" message=\"A simple text-only banner without any icon.\" showIcon={false} dismissible={false} />\n                    <PageBanner\n                        type=\"success\"\n                        title=\"Minimal Success\"\n                        message=\"Sometimes less is more. No icon, just the message.\"\n                        showIcon={false}\n                        dismissible={false}\n                    />\n                </div>\n            </ComponentDemo>\n\n            <ComponentDemo title=\"With Title\" description=\"Add a title to give the banner a bold heading above the message.\">\n                <div className=\"space-y-4\">\n                    <PageBanner\n                        type=\"info\"\n                        title=\"Did You Know?\"\n                        message=\"You can customize the appearance of banners using the type, bordered, and className props.\"\n                        dismissible={false}\n                    />\n                    <PageBanner\n                        type=\"error\"\n                        title=\"Payment Failed\"\n                        message=\"Your payment could not be processed. Please update your billing information and try again.\"\n                        dismissible={false}\n                        bordered\n                    />\n                </div>\n            </ComponentDemo>\n        </>\n    );\n};\n\nexport default CustomContent;\n"
        },
        {
          "title": "Dismissible",
          "code": "import React, { useCallback, useState } from 'react';\nimport { Button, PageBanner } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst dismissibleCode = `import { PageBanner } from 'fluxo-ui';\n\nconst [visible, setVisible] = useState(true);\n\n<PageBanner\n  type=\"info\"\n  message=\"Click the X to dismiss this banner.\"\n  dismissible\n  visible={visible}\n  onDismiss={() => setVisible(false)}\n/>`;\n\nconst autoDismissCode = `import { PageBanner } from 'fluxo-ui';\n\n<PageBanner\n  type=\"success\"\n  message=\"This banner will auto-dismiss in 5 seconds.\"\n  autoDismiss={5000}\n  onDismiss={() => console.log('Dismissed!')}\n/>`;\n\nconst Dismissible: React.FC = () => {\n    const [dismissibleVisible, setDismissibleVisible] = useState(true);\n    const [autoVisible, setAutoVisible] = useState(true);\n    const [nonDismissibleKey] = useState(0);\n\n    const resetDismissible = useCallback(() => {\n        setDismissibleVisible(true);\n    }, []);\n\n    const resetAuto = useCallback(() => {\n        setAutoVisible(false);\n        setTimeout(() => setAutoVisible(true), 100);\n    }, []);\n\n    return (\n        <>\n            <ComponentDemo title=\"Dismissible Banner\" description=\"Banners can be dismissed by clicking the close button.\">\n                <div className=\"space-y-4\">\n                    <PageBanner\n                        type=\"info\"\n                        message=\"Click the X button to dismiss this banner.\"\n                        dismissible\n                        visible={dismissibleVisible}\n                        onDismiss={() => setDismissibleVisible(false)}\n                    />\n                    {!dismissibleVisible && (\n                        <Button variant=\"primary\" size=\"sm\" onClick={resetDismissible}>\n                            Show Again\n                        </Button>\n                    )}\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={dismissibleCode} language=\"tsx\" />\n            </div>\n\n            <ComponentDemo title=\"Auto-Dismiss\" description=\"Banners can auto-dismiss after a set duration with a progress bar indicator.\">\n                <div className=\"space-y-4\">\n                    {autoVisible && (\n                        <PageBanner\n                            type=\"success\"\n                            message=\"This banner will auto-dismiss in 5 seconds. Watch the progress bar!\"\n                            autoDismiss={5000}\n                            onDismiss={() => setAutoVisible(false)}\n                        />\n                    )}\n                    {!autoVisible && (\n                        <Button variant=\"primary\" size=\"sm\" onClick={resetAuto}>\n                            Trigger Auto-Dismiss Banner\n                        </Button>\n                    )}\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={autoDismissCode} language=\"tsx\" />\n            </div>\n\n            <ComponentDemo title=\"Non-Dismissible\" description=\"Set dismissible to false to prevent the user from closing the banner.\">\n                <PageBanner\n                    key={nonDismissibleKey}\n                    type=\"warning\"\n                    message=\"This banner cannot be dismissed by the user. It remains visible until programmatically hidden.\"\n                    dismissible={false}\n                />\n            </ComponentDemo>\n        </>\n    );\n};\n\nexport default Dismissible;\n"
        },
        {
          "title": "PageLevel",
          "code": "import React, { useState } from 'react';\nimport { Button, PageBanner } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst pageLevelCode = `import { PageBanner } from 'fluxo-ui';\n\n<PageBanner\n  type=\"error\"\n  message=\"Service maintenance scheduled for tonight.\"\n  pageLevel\n  onDismiss={() => setVisible(false)}\n/>`;\n\nconst borderedCode = `import { PageBanner } from 'fluxo-ui';\n\n<PageBanner\n  type=\"info\"\n  message=\"Bordered banner with a left accent.\"\n  bordered\n/>`;\n\nconst PageLevel: React.FC = () => {\n    const [pageLevelVisible, setPageLevelVisible] = useState(false);\n    const [pageLevelType, setPageLevelType] = useState<'info' | 'success' | 'warning' | 'error'>('error');\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Page-Level Banner\"\n                description=\"Page-level banners use createPortal to render at the top of the page, above all other content.\"\n            >\n                <div className=\"flex flex-wrap gap-3\">\n                    <Button\n                        variant=\"primary\"\n                        onClick={() => {\n                            setPageLevelType('error');\n                            setPageLevelVisible(true);\n                        }}\n                    >\n                        Show Error Banner\n                    </Button>\n                    <Button\n                        variant=\"primary\"\n                        layout=\"outlined\"\n                        onClick={() => {\n                            setPageLevelType('warning');\n                            setPageLevelVisible(true);\n                        }}\n                    >\n                        Show Warning Banner\n                    </Button>\n                    <Button\n                        variant=\"primary\"\n                        layout=\"outlined\"\n                        onClick={() => {\n                            setPageLevelType('info');\n                            setPageLevelVisible(true);\n                        }}\n                    >\n                        Show Info Banner\n                    </Button>\n                    <Button\n                        variant=\"primary\"\n                        layout=\"outlined\"\n                        onClick={() => {\n                            setPageLevelType('success');\n                            setPageLevelVisible(true);\n                        }}\n                    >\n                        Show Success Banner\n                    </Button>\n                </div>\n                {pageLevelVisible && (\n                    <PageBanner\n                        type={pageLevelType}\n                        title=\"Page-Level Notification\"\n                        message=\"This banner is rendered via createPortal at the top of the page body.\"\n                        pageLevel\n                        visible={pageLevelVisible}\n                        onDismiss={() => setPageLevelVisible(false)}\n                    />\n                )}\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={pageLevelCode} language=\"tsx\" />\n            </div>\n\n            <ComponentDemo title=\"Bordered Banner\" description=\"Add a left border accent using the bordered prop.\">\n                <div className=\"space-y-4\">\n                    <PageBanner type=\"info\" message=\"Bordered info banner with a left accent line.\" bordered dismissible={false} />\n                    <PageBanner type=\"success\" message=\"Bordered success banner with a left accent line.\" bordered dismissible={false} />\n                    <PageBanner type=\"warning\" message=\"Bordered warning banner with a left accent line.\" bordered dismissible={false} />\n                    <PageBanner type=\"error\" message=\"Bordered error banner with a left accent line.\" bordered dismissible={false} />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={borderedCode} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default PageLevel;\n"
        },
        {
          "title": "WithActions",
          "code": "import React, { useState } from 'react';\nimport { Button, PageBanner } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { PageBanner, Button } from 'fluxo-ui';\n\n<PageBanner\n  type=\"warning\"\n  title=\"Update Available\"\n  message=\"A new version is available.\"\n  actions={\n    <div className=\"flex gap-2\">\n      <Button size=\"sm\" variant=\"primary\">Update Now</Button>\n      <Button size=\"sm\" variant=\"default\">Later</Button>\n    </div>\n  }\n/>`;\n\nconst WithActions: React.FC = () => {\n    const [updateVisible, setUpdateVisible] = useState(true);\n    const [cookieVisible, setCookieVisible] = useState(true);\n    const [trialVisible, setTrialVisible] = useState(true);\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Banner with Actions\"\n                description=\"Add action buttons using the actions prop to let users take immediate action.\"\n            >\n                <div className=\"space-y-4\">\n                    {updateVisible && (\n                        <PageBanner\n                            type=\"warning\"\n                            title=\"Update Available\"\n                            message=\"A new version of the application is available. Update now to get the latest features and security fixes.\"\n                            actions={\n                                <div className=\"flex gap-2\">\n                                    <Button size=\"sm\" variant=\"primary\" onClick={() => setUpdateVisible(false)}>\n                                        Update Now\n                                    </Button>\n                                    <Button size=\"sm\" variant=\"default\" onClick={() => setUpdateVisible(false)}>\n                                        Later\n                                    </Button>\n                                </div>\n                            }\n                            onDismiss={() => setUpdateVisible(false)}\n                        />\n                    )}\n\n                    {cookieVisible && (\n                        <PageBanner\n                            type=\"info\"\n                            title=\"Cookie Consent\"\n                            message=\"We use cookies to enhance your browsing experience. By continuing, you agree to our cookie policy.\"\n                            actions={\n                                <div className=\"flex gap-2\">\n                                    <Button size=\"sm\" variant=\"primary\" onClick={() => setCookieVisible(false)}>\n                                        Accept All\n                                    </Button>\n                                    <Button size=\"sm\" variant=\"default\" layout=\"outlined\" onClick={() => setCookieVisible(false)}>\n                                        Customize\n                                    </Button>\n                                </div>\n                            }\n                            onDismiss={() => setCookieVisible(false)}\n                        />\n                    )}\n\n                    {trialVisible && (\n                        <PageBanner\n                            type=\"error\"\n                            title=\"Trial Expired\"\n                            message=\"Your free trial has ended. Upgrade to continue using premium features.\"\n                            dismissible={false}\n                            actions={\n                                <Button size=\"sm\" variant=\"primary\" onClick={() => setTrialVisible(false)}>\n                                    Upgrade Now\n                                </Button>\n                            }\n                        />\n                    )}\n\n                    {(!updateVisible || !cookieVisible || !trialVisible) && (\n                        <Button\n                            variant=\"primary\"\n                            size=\"sm\"\n                            onClick={() => {\n                                setUpdateVisible(true);\n                                setCookieVisible(true);\n                                setTrialVisible(true);\n                            }}\n                        >\n                            Reset All Banners\n                        </Button>\n                    )}\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default WithActions;\n"
        }
      ],
      "props": {
        "pageBannerProps": {
          "type": {
            "type": "'info' | 'success' | 'warning' | 'error' | 'default'",
            "default": "'info'",
            "description": "The visual style of the banner."
          },
          "message": {
            "type": "ReactNode",
            "required": true,
            "description": "The main content of the banner. Accepts text or JSX."
          },
          "title": {
            "type": "string",
            "description": "An optional bold heading displayed above the message."
          },
          "headingLevel": {
            "type": "1 | 2 | 3 | 4 | 5 | 6",
            "default": "3",
            "description": "Heading element used for the title (h1-h6) so the page heading outline includes the banner."
          },
          "icon": {
            "type": "ReactNode",
            "description": "Custom icon to replace the default type-based icon."
          },
          "showIcon": {
            "type": "boolean",
            "default": "true",
            "description": "Whether to display an icon in the banner."
          },
          "dismissible": {
            "type": "boolean",
            "default": "true",
            "description": "Whether the banner can be dismissed via a close button."
          },
          "autoDismiss": {
            "type": "number",
            "description": "Auto-dismiss after this many milliseconds. Shows a progress bar."
          },
          "onDismiss": {
            "type": "() => void",
            "description": "Callback fired when the banner is dismissed."
          },
          "visible": {
            "type": "boolean",
            "default": "true",
            "description": "Controls the visibility of the banner externally."
          },
          "position": {
            "type": "'top' | 'inline'",
            "default": "'inline'",
            "description": "Position of the banner. Top sticks to viewport top."
          },
          "pageLevel": {
            "type": "boolean",
            "default": "false",
            "description": "When true, renders the banner via createPortal to document.body."
          },
          "pushContent": {
            "type": "boolean",
            "default": "false",
            "description": "When combined with pageLevel, pushes page content down."
          },
          "className": {
            "type": "string",
            "description": "Additional CSS class name for custom styling."
          },
          "actions": {
            "type": "ReactNode",
            "description": "Action buttons or elements rendered alongside the message."
          },
          "bordered": {
            "type": "boolean",
            "default": "false",
            "description": "Adds a left border accent matching the banner type color."
          },
          "restoreFocusOnDismiss": {
            "type": "boolean",
            "default": "true",
            "description": "On dismiss, return focus to the element that was focused when the banner appeared."
          }
        }
      },
      "storyDir": "page-banner"
    },
    "PasswordRequirements": {
      "name": "PasswordRequirements",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React, { useState } from 'react';\nimport { Password, PasswordRequirements } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { Password, PasswordRequirements } from 'fluxo-ui';\n\nconst [pw, setPw] = useState('');\nconst [cpw, setCpw] = useState('');\n\n<Password value={pw} onChange={(e) => setPw(e.value)} autoComplete=\"new-password\" />\n<Password value={cpw} onChange={(e) => setCpw(e.value)} autoComplete=\"new-password\" placeholder=\"Confirm password\" />\n\n<PasswordRequirements\n  value={pw}\n  confirm={cpw}\n  policy={{\n    minLength: 8,\n    minLowercase: 1,\n    minUppercase: 1,\n    minDigits: 1,\n    minSymbols: 1,\n    maxConsecutiveRepeat: 2,\n    maxConsecutiveSequence: 4,\n  }}\n/>`;\n\nconst BasicUsage: React.FC = () => {\n    const [pw, setPw] = useState('');\n    const [cpw, setCpw] = useState('');\n    return (\n        <>\n            <ComponentDemo\n                title=\"Default Requirements List\"\n                description=\"Type in both fields and watch each rule check itself off live.\"\n            >\n                <div style={{ width: '100%', maxWidth: 480, display: 'flex', flexDirection: 'column', gap: 12 }}>\n                    <Password\n                        value={pw}\n                        onChange={(e) => setPw(e.value)}\n                        autoComplete=\"new-password\"\n                        placeholder=\"Password\"\n                    />\n                    <Password\n                        value={cpw}\n                        onChange={(e) => setCpw(e.value)}\n                        autoComplete=\"new-password\"\n                        placeholder=\"Confirm password\"\n                    />\n                    <PasswordRequirements\n                        value={pw}\n                        confirm={cpw}\n                        policy={{\n                            minLength: 8,\n                            minLowercase: 1,\n                            minUppercase: 1,\n                            minDigits: 1,\n                            minSymbols: 1,\n                            maxConsecutiveRepeat: 2,\n                            maxConsecutiveSequence: 4,\n                        }}\n                    />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "Configurable",
          "code": "import React, { useState } from 'react';\nimport { PasswordRequirements } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<PasswordRequirements\n  value={pw}\n  policy={{\n    minLength: 12,\n    maxLength: 64,\n    minLowercase: 2,\n    minUppercase: 2,\n    minDigits: 2,\n    minSymbols: 1,\n    allowedSymbols: '!@#$%&*',\n    forbidWhitespace: true,\n    maxConsecutiveRepeat: 2,\n    maxConsecutiveSequence: 4,\n  }}\n/>`;\n\nconst Configurable: React.FC = () => {\n    const [pw, setPw] = useState('');\n    const [minLength, setMinLength] = useState(12);\n    const [minSymbols, setMinSymbols] = useState(1);\n    const [allowedSymbols, setAllowedSymbols] = useState('!@#$%&*');\n    const [forbidWhitespace, setForbidWhitespace] = useState(true);\n    const [maxRepeat, setMaxRepeat] = useState(2);\n    const [maxSeq, setMaxSeq] = useState(4);\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Live Policy Tuning\"\n                description=\"Drive every built-in rule with controls so you can see how each setting changes the checklist.\"\n            >\n                <div style={{ width: '100%', maxWidth: 560, display: 'flex', flexDirection: 'column', gap: 14 }}>\n                    <input\n                        type=\"text\"\n                        value={pw}\n                        onChange={(e) => setPw(e.target.value)}\n                        placeholder=\"Type a password\"\n                        style={{\n                            padding: '6px 10px',\n                            borderRadius: 4,\n                            border: '1px solid var(--eui-border)',\n                            background: 'var(--eui-bg)',\n                            color: 'var(--eui-text)',\n                            fontSize: 14,\n                            fontFamily: 'inherit',\n                        }}\n                    />\n\n                    <PasswordRequirements\n                        value={pw}\n                        policy={{\n                            minLength,\n                            maxLength: 64,\n                            minLowercase: 2,\n                            minUppercase: 2,\n                            minDigits: 2,\n                            minSymbols,\n                            allowedSymbols,\n                            forbidWhitespace,\n                            maxConsecutiveRepeat: maxRepeat,\n                            maxConsecutiveSequence: maxSeq,\n                        }}\n                    />\n\n                    <div\n                        style={{\n                            display: 'grid',\n                            gridTemplateColumns: 'auto 1fr auto',\n                            gap: 12,\n                            alignItems: 'center',\n                            padding: '12px 16px',\n                            background: 'var(--eui-bg-subtle)',\n                            border: '1px solid var(--eui-border-subtle)',\n                            borderRadius: 6,\n                            fontSize: 13,\n                        }}\n                    >\n                        <label htmlFor=\"pr-minl\">Min length</label>\n                        <input id=\"pr-minl\" type=\"range\" min={4} max={32} value={minLength} onChange={(e) => setMinLength(Number(e.target.value))} />\n                        <span>{minLength}</span>\n\n                        <label htmlFor=\"pr-minsym\">Min symbols</label>\n                        <input id=\"pr-minsym\" type=\"range\" min={0} max={4} value={minSymbols} onChange={(e) => setMinSymbols(Number(e.target.value))} />\n                        <span>{minSymbols}</span>\n\n                        <label htmlFor=\"pr-syms\">Allowed symbols</label>\n                        <input\n                            id=\"pr-syms\"\n                            type=\"text\"\n                            value={allowedSymbols}\n                            onChange={(e) => setAllowedSymbols(e.target.value)}\n                            style={{\n                                padding: '4px 8px',\n                                borderRadius: 4,\n                                border: '1px solid var(--eui-border)',\n                                background: 'var(--eui-bg)',\n                                color: 'var(--eui-text)',\n                                fontFamily: 'monospace',\n                            }}\n                        />\n                        <span style={{ fontFamily: 'monospace' }}>{allowedSymbols.length}</span>\n\n                        <label htmlFor=\"pr-ws\">Forbid whitespace</label>\n                        <input id=\"pr-ws\" type=\"checkbox\" checked={forbidWhitespace} onChange={(e) => setForbidWhitespace(e.target.checked)} />\n                        <span>{forbidWhitespace ? 'on' : 'off'}</span>\n\n                        <label htmlFor=\"pr-repeat\">Max repeat</label>\n                        <input id=\"pr-repeat\" type=\"range\" min={0} max={5} value={maxRepeat} onChange={(e) => setMaxRepeat(Number(e.target.value))} />\n                        <span>{maxRepeat || 'off'}</span>\n\n                        <label htmlFor=\"pr-seq\">Max sequence</label>\n                        <input id=\"pr-seq\" type=\"range\" min={0} max={6} value={maxSeq} onChange={(e) => setMaxSeq(Number(e.target.value))} />\n                        <span>{maxSeq || 'off'}</span>\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default Configurable;\n"
        },
        {
          "title": "CustomRules",
          "code": "import React, { useState } from 'react';\nimport { PasswordRequirements } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<PasswordRequirements\n  value={pw}\n  policy={{ minLength: 8 }}\n  customRules={[\n    { id: 'noEmail', label: \"Doesn't contain '@'\", test: (v) => !v.includes('@') },\n    { id: 'startsLetter', label: 'Starts with a letter', test: (v) => /^[A-Za-z]/.test(v) },\n    { id: 'noYear', label: \"Doesn't contain '2024' or '2025'\", test: (v) => !/(2024|2025)/.test(v) },\n  ]}\n  labels={{ minLength: 'Be at least 8 characters' }}\n/>`;\n\nconst CustomRules: React.FC = () => {\n    const [pw, setPw] = useState('');\n    return (\n        <>\n            <ComponentDemo\n                title=\"Custom Rules & Label Overrides\"\n                description=\"Add any rule the policy doesn't cover, and override built-in labels with the labels prop.\"\n            >\n                <div style={{ width: '100%', maxWidth: 480, display: 'flex', flexDirection: 'column', gap: 12 }}>\n                    <input\n                        type=\"text\"\n                        value={pw}\n                        onChange={(e) => setPw(e.target.value)}\n                        placeholder=\"Try typing your name or 'admin@2024'\"\n                        style={{\n                            padding: '6px 10px',\n                            borderRadius: 4,\n                            border: '1px solid var(--eui-border)',\n                            background: 'var(--eui-bg)',\n                            color: 'var(--eui-text)',\n                            fontSize: 14,\n                            fontFamily: 'inherit',\n                        }}\n                    />\n                    <PasswordRequirements\n                        value={pw}\n                        policy={{ minLength: 8, minDigits: 1 }}\n                        customRules={[\n                            { id: 'noEmail', label: \"Doesn't contain '@'\", test: (v) => v.length === 0 ? false : !v.includes('@') },\n                            { id: 'startsLetter', label: 'Starts with a letter', test: (v) => /^[A-Za-z]/.test(v) },\n                            { id: 'noYear', label: \"Doesn't contain '2024' or '2025'\", test: (v) => v.length === 0 ? false : !/(2024|2025)/.test(v) },\n                        ]}\n                        labels={{ minLength: 'Be at least 8 characters', minDigits: 'Include a digit' }}\n                    />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default CustomRules;\n"
        },
        {
          "title": "NumericPin",
          "code": "import React, { useState } from 'react';\nimport { PasswordRequirements } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<PasswordRequirements\n  value={pin}\n  policy={{\n    numericOnly: true,\n    minLength: 6,\n    maxLength: 6,\n    maxConsecutiveRepeat: 2,\n    maxConsecutiveSequence: 3,\n  }}\n  variant=\"card\"\n  title=\"Set a 6-digit PIN\"\n/>`;\n\nconst NumericPin: React.FC = () => {\n    const [pin, setPin] = useState('');\n    return (\n        <>\n            <ComponentDemo\n                title=\"Numeric PIN Use Case\"\n                description=\"numericOnly + min/max length + repeat/sequence limits — perfect for a banking PIN form.\"\n            >\n                <div style={{ width: '100%', maxWidth: 360, display: 'flex', flexDirection: 'column', gap: 12 }}>\n                    <input\n                        type=\"text\"\n                        inputMode=\"numeric\"\n                        value={pin}\n                        onChange={(e) => setPin(e.target.value.replace(/\\D/g, '').slice(0, 6))}\n                        placeholder=\"6-digit PIN\"\n                        maxLength={6}\n                        style={{\n                            padding: '8px 12px',\n                            borderRadius: 4,\n                            border: '1px solid var(--eui-border)',\n                            background: 'var(--eui-bg)',\n                            color: 'var(--eui-text)',\n                            fontSize: 18,\n                            letterSpacing: 4,\n                            fontFamily: 'monospace',\n                            textAlign: 'center',\n                        }}\n                    />\n                    <PasswordRequirements\n                        value={pin}\n                        variant=\"card\"\n                        title=\"Set a 6-digit PIN\"\n                        policy={{\n                            numericOnly: true,\n                            minLength: 6,\n                            maxLength: 6,\n                            maxConsecutiveRepeat: 2,\n                            maxConsecutiveSequence: 3,\n                        }}\n                    />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default NumericPin;\n"
        },
        {
          "title": "Variants",
          "code": "import React, { useState } from 'react';\nimport { PasswordRequirements, PasswordRequirementsIconStyle, PasswordRequirementsVariant } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<PasswordRequirements value={pw} variant=\"list\" iconStyle=\"check\" policy={policy} />\n<PasswordRequirements value={pw} variant=\"inline\" iconStyle=\"dot\" policy={policy} />\n<PasswordRequirements value={pw} variant=\"card\" iconStyle=\"numeric\" policy={policy} title=\"Password rules\" />`;\n\nconst variants: PasswordRequirementsVariant[] = ['list', 'inline', 'card'];\nconst iconStyles: PasswordRequirementsIconStyle[] = ['check', 'dot', 'numeric'];\n\nconst Variants: React.FC = () => {\n    const [pw, setPw] = useState('helloWorld!');\n    return (\n        <>\n            <ComponentDemo\n                title=\"Variants × Icon Styles\"\n                description=\"Three visual variants × three icon styles. Pick what fits your form layout.\"\n            >\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16 }}>\n                    <input\n                        type=\"text\"\n                        value={pw}\n                        onChange={(e) => setPw(e.target.value)}\n                        placeholder=\"Type a password\"\n                        style={{\n                            padding: '6px 10px',\n                            borderRadius: 4,\n                            border: '1px solid var(--eui-border)',\n                            background: 'var(--eui-bg)',\n                            color: 'var(--eui-text)',\n                            fontSize: 14,\n                            fontFamily: 'inherit',\n                            maxWidth: 480,\n                        }}\n                    />\n                    {variants.map((v) =>\n                        iconStyles.map((icon) => (\n                            <div\n                                key={`${v}-${icon}`}\n                                style={{\n                                    padding: '12px 14px',\n                                    background: 'var(--eui-bg-subtle)',\n                                    border: '1px solid var(--eui-border-subtle)',\n                                    borderRadius: 6,\n                                }}\n                            >\n                                <div\n                                    style={{\n                                        fontSize: 11,\n                                        color: 'var(--eui-text-muted)',\n                                        marginBottom: 8,\n                                        fontFamily: 'monospace',\n                                    }}\n                                >\n                                    variant=\"{v}\" iconStyle=\"{icon}\"\n                                </div>\n                                <PasswordRequirements\n                                    value={pw}\n                                    variant={v}\n                                    iconStyle={icon}\n                                    title=\"Requirements\"\n                                    policy={{\n                                        minLength: 8,\n                                        minLowercase: 1,\n                                        minUppercase: 1,\n                                        minDigits: 1,\n                                        minSymbols: 1,\n                                    }}\n                                />\n                            </div>\n                        )),\n                    )}\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default Variants;\n"
        },
        {
          "title": "WithStrength",
          "code": "import React, { useState } from 'react';\nimport { Password, PasswordRequirements } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<PasswordRequirements\n  value={pw}\n  confirm={cpw}\n  showStrengthMeter\n  strengthMeterProps={{ meterStyle: 'segments' }}\n  policy={{ minLength: 10, minLowercase: 1, minUppercase: 1, minDigits: 1, minSymbols: 1 }}\n  variant=\"card\"\n  title=\"Create a strong password\"\n/>`;\n\nconst WithStrength: React.FC = () => {\n    const [pw, setPw] = useState('');\n    const [cpw, setCpw] = useState('');\n    return (\n        <>\n            <ComponentDemo\n                title=\"Embedded Strength Meter\"\n                description=\"Set showStrengthMeter to bundle the strength meter inside the requirements component.\"\n            >\n                <div style={{ width: '100%', maxWidth: 480, display: 'flex', flexDirection: 'column', gap: 12 }}>\n                    <Password\n                        value={pw}\n                        onChange={(e) => setPw(e.value)}\n                        autoComplete=\"new-password\"\n                        placeholder=\"Password\"\n                    />\n                    <Password\n                        value={cpw}\n                        onChange={(e) => setCpw(e.value)}\n                        autoComplete=\"new-password\"\n                        placeholder=\"Confirm password\"\n                    />\n                    <PasswordRequirements\n                        value={pw}\n                        confirm={cpw}\n                        showStrengthMeter\n                        strengthMeterProps={{ meterStyle: 'segments' }}\n                        variant=\"card\"\n                        title=\"Create a strong password\"\n                        policy={{\n                            minLength: 10,\n                            minLowercase: 1,\n                            minUppercase: 1,\n                            minDigits: 1,\n                            minSymbols: 1,\n                            maxConsecutiveRepeat: 2,\n                            maxConsecutiveSequence: 4,\n                        }}\n                    />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default WithStrength;\n"
        }
      ],
      "props": {
        "passwordRequirementsProps": {
          "value": {
            "type": "string",
            "required": true,
            "description": "Current password value"
          },
          "confirm": {
            "type": "string",
            "description": "Optional confirm-password value. When provided, the equality rule is enabled by default"
          },
          "policy": {
            "type": "PasswordRequirementsPolicy",
            "description": "Built-in rules. All keys are optional — only enabled rules appear in the UI: { minLength?, maxLength?, minLowercase?, minUppercase?, minDigits?, minSymbols?, allowedSymbols?, forbidWhitespace?, maxConsecutiveRepeat?, maxConsecutiveSequence?, requireMatch?, onlyAlphaNumeric?, numericOnly?, customCharSet? }"
          },
          "customRules": {
            "type": "Array<{ id, label, test(value, confirm?), hint? }>",
            "description": "Additional rules merged below the built-in ones"
          },
          "labels": {
            "type": "Partial<Record<string, string>>",
            "description": "Override the wording of any built-in or custom rule by id"
          },
          "showStrengthMeter": {
            "type": "boolean",
            "default": "false",
            "description": "Render the bundled PasswordStrengthMeter below the checklist"
          },
          "strengthMeterProps": {
            "type": "Omit<PasswordStrengthMeterProps, 'value'>",
            "description": "Forwarded to the embedded PasswordStrengthMeter"
          },
          "variant": {
            "type": "'list' | 'inline' | 'card'",
            "default": "'list'",
            "description": "Visual treatment"
          },
          "size": {
            "type": "'sm' | 'md' | 'lg'",
            "default": "'md'",
            "description": "Compact, comfortable, or relaxed scale"
          },
          "iconStyle": {
            "type": "'check' | 'dot' | 'numeric'",
            "default": "'check'",
            "description": "Visual treatment of the satisfied state"
          },
          "hideOnMet": {
            "type": "boolean",
            "default": "false",
            "description": "Collapse satisfied rules out of view (still announced once for SR)"
          },
          "title": {
            "type": "string",
            "description": "Header for the 'card' variant"
          },
          "onChange": {
            "type": "(info: PasswordRequirementsInfo) => void",
            "description": "Fires when any rule's met state changes"
          },
          "id": {
            "type": "string",
            "description": "HTML id attribute"
          },
          "className": {
            "type": "string",
            "description": "Additional CSS classes"
          },
          "ariaLabel": {
            "type": "string",
            "description": "Accessible label override"
          }
        }
      },
      "storyDir": "password-requirements"
    },
    "PasswordStrengthMeter": {
      "name": "PasswordStrengthMeter",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {
        "passwordStrengthMeterProps": {
          "value": {
            "type": "string",
            "required": true,
            "description": "Current password value"
          },
          "policy": {
            "type": "PasswordPolicy",
            "description": "Rule configuration: { minLength?, targetLength?, requireLowercase?, requireUppercase?, requireDigit?, requireSymbol?, forbidSequences?, forbidRepeats?, forbidCommon? }"
          },
          "allowedChars": {
            "type": "{ lowercase?: boolean; uppercase?: boolean; digits?: boolean; symbols?: boolean | string }",
            "description": "What the field accepts. The meter only scores classes that are allowed and only emits tips that respect this"
          },
          "commonPasswords": {
            "type": "string[]",
            "description": "Extra entries to merge into the default ~50-entry blocklist"
          },
          "useDefaultBlocklist": {
            "type": "boolean",
            "default": "true",
            "description": "Include the default common-password blocklist"
          },
          "thresholds": {
            "type": "{ fair?: number; good?: number; strong?: number }",
            "default": "{ fair: 40, good: 65, strong: 85 }",
            "description": "Score boundaries between tiers"
          },
          "showTips": {
            "type": "boolean",
            "default": "true",
            "description": "Render an actionable tip line below the meter"
          },
          "showLabel": {
            "type": "boolean",
            "default": "true",
            "description": "Render the tier label ('Weak', 'Strong', etc.)"
          },
          "customRules": {
            "type": "Array<PasswordRule>",
            "description": "Additional rules: { id, weight, test(value), hint(value) }"
          },
          "meterStyle": {
            "type": "'segments' | 'bar' | 'minimal'",
            "default": "'segments'",
            "description": "Visual treatment"
          },
          "size": {
            "type": "'sm' | 'md' | 'lg'",
            "default": "'md'",
            "description": "Meter and font scale"
          },
          "id": {
            "type": "string",
            "description": "HTML id attribute"
          },
          "className": {
            "type": "string",
            "description": "Additional CSS classes"
          },
          "ariaLabel": {
            "type": "string",
            "description": "Accessible label override"
          },
          "onScoreChange": {
            "type": "(info: PasswordStrengthInfo) => void",
            "description": "Fires whenever the tier changes"
          }
        }
      }
    },
    "Picker": {
      "name": "Picker",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React, { useState } from 'react';\nimport { Picker } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { Picker } from 'fluxo-ui';\n\nconst [value, setValue] = useState(['medium']);\n\n<Picker\n    columns={[{\n        key: 'size',\n        label: 'T-shirt size',\n        options: [\n            { value: 'xs', label: 'XS' },\n            { value: 's', label: 'S' },\n            { value: 'medium', label: 'M' },\n            { value: 'l', label: 'L' },\n            { value: 'xl', label: 'XL' },\n        ],\n    }]}\n    value={value}\n    onChange={setValue}\n/>`;\n\nconst options = ['XS', 'S', 'M', 'L', 'XL', 'XXL'].map((s) => ({ value: s.toLowerCase(), label: s }));\n\nconst noteBox: React.CSSProperties = {\n    padding: '10px 14px',\n    background: 'var(--eui-bg-subtle)',\n    border: '1px solid var(--eui-border-subtle)',\n    borderRadius: 6,\n    fontSize: 12,\n    color: 'var(--eui-text-muted)',\n};\n\nconst BasicUsage: React.FC = () => {\n    const [value, setValue] = useState<string[]>(['m']);\n    return (\n        <>\n            <ComponentDemo title=\"Single-column picker\" description=\"Scroll the wheel to settle on a value. Outer rows fade and shrink for the classic iOS feel.\">\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16, maxWidth: 240 }}>\n                    <div style={{ border: '1px solid var(--eui-border-subtle)', borderRadius: 8, padding: '8px 0' }}>\n                        <Picker columns={[{ key: 'size', label: 'Size', options }]} value={value} onChange={setValue} />\n                    </div>\n                    <div style={noteBox}>Selected: <strong style={{ color: 'var(--eui-text)' }}>{value.join(', ')}</strong></div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\"><CodeBlock code={code} language=\"tsx\" /></div>\n        </>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "InSheet",
          "code": "import React, { useState } from 'react';\nimport { Button, Drawer, Picker } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<Button label=\"Pick a country\" onClick={() => setOpen(true)} />\n<Drawer\n    open={open}\n    onClose={() => setOpen(false)}\n    position=\"bottom\"\n    variant=\"sheet\"\n    snapPoints={['45%']}\n    title=\"Pick a country\"\n    footer={<Button label=\"Done\" onClick={() => setOpen(false)} />}\n>\n    <Picker columns={[{ options: countries }]} value={value} onChange={setValue} />\n</Drawer>`;\n\nconst countries = ['India', 'Indonesia', 'Ireland', 'Israel', 'Italy', 'Iceland'].map((s) => ({ value: s.toLowerCase(), label: s }));\n\nconst noteBox: React.CSSProperties = {\n    padding: '10px 14px',\n    background: 'var(--eui-bg-subtle)',\n    border: '1px solid var(--eui-border-subtle)',\n    borderRadius: 6,\n    fontSize: 12,\n    color: 'var(--eui-text-muted)',\n};\n\nconst InSheet: React.FC = () => {\n    const [open, setOpen] = useState(false);\n    const [value, setValue] = useState<string[]>(['india']);\n\n    return (\n        <>\n            <ComponentDemo title=\"Picker inside a bottom sheet\" description=\"Pair the Picker with a Drawer in sheet mode for a familiar mobile selection pattern.\">\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16 }}>\n                    <div>\n                        <Button label={`Country: ${countries.find((c) => c.value === value[0])?.label}`} onClick={() => setOpen(true)} />\n                    </div>\n                    <div style={noteBox}>Picker value: <strong style={{ color: 'var(--eui-text)' }}>{value[0]}</strong></div>\n                </div>\n                <Drawer\n                    open={open}\n                    onClose={() => setOpen(false)}\n                    position=\"bottom\"\n                    variant=\"sheet\"\n                    snapPoints={['45%']}\n                    title=\"Pick a country\"\n                    footer={<Button label=\"Done\" onClick={() => setOpen(false)} />}\n                >\n                    <Picker columns={[{ options: countries }]} value={value} onChange={setValue} />\n                </Drawer>\n            </ComponentDemo>\n            <div className=\"mt-4\"><CodeBlock code={code} language=\"tsx\" /></div>\n        </>\n    );\n};\n\nexport default InSheet;\n"
        },
        {
          "title": "MultiColumn",
          "code": "import React, { useMemo, useState } from 'react';\nimport { Picker } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<Picker\n    columns={[\n        { key: 'hour', label: 'Hour', options: hours },\n        { key: 'min', label: 'Min', options: minutes },\n        { key: 'ampm', label: '', options: [{ value: 'AM', label: 'AM' }, { value: 'PM', label: 'PM' }] },\n    ]}\n    value={time}\n    onChange={setTime}\n/>`;\n\nconst noteBox: React.CSSProperties = {\n    padding: '10px 14px',\n    background: 'var(--eui-bg-subtle)',\n    border: '1px solid var(--eui-border-subtle)',\n    borderRadius: 6,\n    fontSize: 12,\n    color: 'var(--eui-text-muted)',\n};\n\nconst MultiColumn: React.FC = () => {\n    const hours = useMemo(() => Array.from({ length: 12 }, (_, i) => ({ value: String(i + 1), label: String(i + 1).padStart(2, '0') })), []);\n    const minutes = useMemo(() => Array.from({ length: 60 }, (_, i) => ({ value: String(i), label: String(i).padStart(2, '0') })), []);\n    const [time, setTime] = useState<string[]>(['9', '30', 'AM']);\n\n    return (\n        <>\n            <ComponentDemo title=\"Time picker (3 columns)\" description=\"Use multiple columns for compound values like time, date, or units. Each column scrolls independently.\">\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16, maxWidth: 320 }}>\n                    <div style={{ border: '1px solid var(--eui-border-subtle)', borderRadius: 8, padding: '8px 0' }}>\n                        <Picker\n                            columns={[\n                                { key: 'hour', label: 'Hour', options: hours },\n                                { key: 'min', label: 'Min', options: minutes },\n                                { key: 'ampm', options: [{ value: 'AM', label: 'AM' }, { value: 'PM', label: 'PM' }] },\n                            ]}\n                            value={time}\n                            onChange={setTime}\n                        />\n                    </div>\n                    <div style={noteBox}>Selected: <strong style={{ color: 'var(--eui-text)' }}>{time[0]}:{time[1].padStart(2, '0')} {time[2]}</strong></div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\"><CodeBlock code={code} language=\"tsx\" /></div>\n        </>\n    );\n};\n\nexport default MultiColumn;\n"
        },
        {
          "title": "Variants",
          "code": "import React, { useState } from 'react';\nimport { Picker } from '../../../components';\nimport type { PickerVariant } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<Picker variant=\"flat\" columns={[...]} value={value} onChange={setValue} />`;\n\nconst fruits = ['Apple', 'Banana', 'Cherry', 'Durian', 'Elderberry', 'Fig'].map((s) => ({ value: s.toLowerCase(), label: s }));\n\nconst VariantPanel: React.FC<{ variant: PickerVariant; title: string; description: string }> = ({ variant, title, description }) => {\n    const [value, setValue] = useState<string[]>(['cherry']);\n    return (\n        <ComponentDemo title={title} description={description}>\n            <div style={{ width: '100%', maxWidth: 220 }}>\n                <div style={{ border: '1px solid var(--eui-border-subtle)', borderRadius: 8 }}>\n                    <Picker variant={variant} columns={[{ options: fruits }]} value={value} onChange={setValue} />\n                </div>\n            </div>\n        </ComponentDemo>\n    );\n};\n\nconst Variants: React.FC = () => (\n    <>\n        <VariantPanel variant=\"wheel\" title=\"Wheel (default)\" description=\"iOS-style with fading and shrinking outer rows.\" />\n        <div className=\"mt-4\">\n            <VariantPanel variant=\"flat\" title=\"Flat\" description=\"Simple highlighted active row, no fade.\" />\n        </div>\n        <div className=\"mt-4\">\n            <VariantPanel variant=\"compact\" title=\"Compact\" description=\"Smaller text — useful when space is tight or when used inline.\" />\n        </div>\n        <div className=\"mt-4\"><CodeBlock code={code} language=\"tsx\" /></div>\n    </>\n);\n\nexport default Variants;\n"
        }
      ],
      "props": {
        "pickerProps": {
          "columns": {
            "type": "PickerColumn[]",
            "required": true,
            "description": "Picker columns. Each column: { key?, label?, options: { value, label, disabled? }[], flex? }."
          },
          "value": {
            "type": "string[]",
            "required": true,
            "description": "Selected value for each column, in order."
          },
          "onChange": {
            "type": "(value: string[]) => void",
            "required": true,
            "description": "Called whenever any column settles on a new option."
          },
          "itemHeight": {
            "type": "number",
            "default": "36",
            "description": "Height in pixels for each row."
          },
          "visibleItems": {
            "type": "number",
            "default": "5",
            "description": "Number of rows visible at once. Odd numbers keep the selected row centered."
          },
          "variant": {
            "type": "'wheel' | 'flat' | 'compact'",
            "default": "'wheel'",
            "description": "Visual style. 'wheel' fades and shrinks outer rows like an iOS picker; 'flat' is a simple highlighted row; 'compact' uses smaller text."
          },
          "disabled": {
            "type": "boolean",
            "default": "false",
            "description": "Disable interaction across all columns."
          },
          "className": {
            "type": "string",
            "description": "Additional CSS class for the picker root."
          },
          "ariaLabel": {
            "type": "string",
            "description": "Accessible name for the picker group."
          }
        }
      },
      "storyDir": "picker"
    },
    "PinInput": {
      "name": "PinInput",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "Advanced",
          "code": "import React, { useState } from 'react';\nimport { PinInput } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<PinInput length={6} groupAfter={3} type=\"numeric\" />\n<PinInput length={8} type=\"alphanumeric\" mask />\n<PinInput length={4} type=\"password\" placeholder=\"•\" />\n<PinInput length={6} invalid errorText=\"Incorrect code\" />`;\n\nconst Advanced: React.FC = () => {\n    const [grouped, setGrouped] = useState('');\n    const [alpha, setAlpha] = useState('');\n    const [pwd, setPwd] = useState('');\n    const [bad, setBad] = useState('123');\n\n    return (\n        <>\n            <ComponentDemo title=\"Grouped digits\" description=\"Insert a visual separator every N fields with groupAfter.\">\n                <PinInput length={6} groupAfter={3} value={grouped} onChange={setGrouped} />\n            </ComponentDemo>\n\n            <ComponentDemo title=\"Alphanumeric + masked\" description=\"type='alphanumeric' allows letters and digits; mask hides characters as dots.\" className=\"mt-4\">\n                <PinInput length={8} type=\"alphanumeric\" mask value={alpha} onChange={setAlpha} />\n            </ComponentDemo>\n\n            <ComponentDemo title=\"Password with placeholder\" description=\"Use type='password' for secret codes; add a placeholder character to indicate empty slots.\" className=\"mt-4\">\n                <PinInput length={4} type=\"password\" placeholder=\"•\" value={pwd} onChange={setPwd} />\n            </ComponentDemo>\n\n            <ComponentDemo title=\"Error state\" description=\"Mark the group invalid and add an errorText to announce the issue via role=alert.\" className=\"mt-4\">\n                <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 8 }}>\n                    <PinInput length={6} invalid value={bad} onChange={setBad} />\n                    <div role=\"alert\" style={{ fontSize: 12, color: '#ef4444' }}>Incorrect code — please try again</div>\n                </div>\n            </ComponentDemo>\n\n            <div className=\"mt-4\"><CodeBlock code={code} language=\"tsx\" /></div>\n        </>\n    );\n};\n\nexport default Advanced;\n"
        },
        {
          "title": "BasicUsage",
          "code": "import React, { useState } from 'react';\nimport { PinInput } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { PinInput } from 'fluxo-ui';\n\nconst [code, setCode] = useState('');\n\n<PinInput\n    length={6}\n    value={code}\n    onChange={setCode}\n    onComplete={(v) => verify(v)}\n    autoFocus\n/>`;\n\nconst noteBox: React.CSSProperties = {\n    padding: '10px 14px',\n    background: 'var(--eui-bg-subtle)',\n    border: '1px solid var(--eui-border-subtle)',\n    borderRadius: 6,\n    fontSize: 12,\n    color: 'var(--eui-text-muted)',\n};\n\nconst BasicUsage: React.FC = () => {\n    const [value, setValue] = useState('');\n    const [complete, setComplete] = useState<string | null>(null);\n    return (\n        <>\n            <ComponentDemo title=\"6-digit code\" description=\"Auto-advances to the next field as the user types. Paste a full code into any field to fill all six.\">\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16 }}>\n                    <PinInput length={6} value={value} onChange={(v) => { setValue(v); setComplete(null); }} onComplete={setComplete} autoFocus />\n                    <div style={noteBox}>Value: <strong style={{ color: 'var(--eui-text)' }}>{value || '—'}</strong>{complete && <> · onComplete fired with <strong style={{ color: 'var(--eui-text)' }}>{complete}</strong></>}</div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\"><CodeBlock code={code} language=\"tsx\" /></div>\n        </>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "Sizes",
          "code": "import React, { useState } from 'react';\nimport { PinInput } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<PinInput length={6} size=\"sm\" />\n<PinInput length={6} size=\"md\" />\n<PinInput length={6} size=\"lg\" />`;\n\nconst Sizes: React.FC = () => {\n    const [sm, setSm] = useState('');\n    const [md, setMd] = useState('');\n    const [lg, setLg] = useState('');\n    return (\n        <>\n            <ComponentDemo title=\"Small\" description=\"Compact fields for inline forms.\">\n                <PinInput length={6} size=\"sm\" value={sm} onChange={setSm} />\n            </ComponentDemo>\n            <ComponentDemo title=\"Medium (default)\" description=\"Balanced size for typical OTP screens.\" className=\"mt-4\">\n                <PinInput length={6} size=\"md\" value={md} onChange={setMd} />\n            </ComponentDemo>\n            <ComponentDemo title=\"Large\" description=\"Bigger touch targets — ideal for sign-in screens on mobile.\" className=\"mt-4\">\n                <PinInput length={6} size=\"lg\" value={lg} onChange={setLg} />\n            </ComponentDemo>\n            <div className=\"mt-4\"><CodeBlock code={code} language=\"tsx\" /></div>\n        </>\n    );\n};\n\nexport default Sizes;\n"
        },
        {
          "title": "Variants",
          "code": "import React, { useState } from 'react';\nimport { PinInput } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<PinInput length={4} variant=\"box\" />\n<PinInput length={4} variant=\"underline\" />\n<PinInput length={4} variant=\"soft\" />`;\n\nconst Variants: React.FC = () => {\n    const [box, setBox] = useState('');\n    const [und, setUnd] = useState('');\n    const [soft, setSoft] = useState('');\n    return (\n        <>\n            <ComponentDemo title=\"Box (default)\" description=\"Bordered tiles — most familiar OTP look.\">\n                <PinInput length={4} value={box} onChange={setBox} />\n            </ComponentDemo>\n            <ComponentDemo title=\"Underline\" description=\"Only a bottom rule — minimal chrome for clean forms.\" className=\"mt-4\">\n                <PinInput length={4} variant=\"underline\" value={und} onChange={setUnd} />\n            </ComponentDemo>\n            <ComponentDemo title=\"Soft\" description=\"Filled background with no visible border — pairs well with light backgrounds.\" className=\"mt-4\">\n                <PinInput length={4} variant=\"soft\" value={soft} onChange={setSoft} />\n            </ComponentDemo>\n            <div className=\"mt-4\"><CodeBlock code={code} language=\"tsx\" /></div>\n        </>\n    );\n};\n\nexport default Variants;\n"
        }
      ],
      "props": {
        "pinInputProps": {
          "length": {
            "type": "number",
            "default": "6",
            "description": "Number of digit/character fields."
          },
          "value": {
            "type": "string",
            "description": "Controlled value of the combined code."
          },
          "defaultValue": {
            "type": "string",
            "default": "''",
            "description": "Initial value when uncontrolled."
          },
          "onChange": {
            "type": "(value: string) => void",
            "description": "Called on every character change."
          },
          "onComplete": {
            "type": "(value: string) => void",
            "description": "Called when all fields are filled."
          },
          "type": {
            "type": "'numeric' | 'alphanumeric' | 'password'",
            "default": "'numeric'",
            "description": "Allowed character set. 'password' also masks input."
          },
          "mask": {
            "type": "boolean",
            "default": "false",
            "description": "Mask characters as dots/asterisks even if type isn't password."
          },
          "variant": {
            "type": "'box' | 'underline' | 'soft'",
            "default": "'box'",
            "description": "Visual style. 'box' is a bordered tile, 'underline' uses a bottom border only, 'soft' uses a filled background."
          },
          "size": {
            "type": "'sm' | 'md' | 'lg'",
            "default": "'md'",
            "description": "Visual size of each field."
          },
          "disabled": {
            "type": "boolean",
            "default": "false",
            "description": "Disable all fields."
          },
          "autoFocus": {
            "type": "boolean",
            "default": "false",
            "description": "Auto-focus the first field on mount."
          },
          "placeholder": {
            "type": "string",
            "default": "''",
            "description": "Placeholder character for empty fields."
          },
          "groupAfter": {
            "type": "number",
            "description": "Insert a visual separator after every N fields (e.g., 3 for 3-3 grouping)."
          },
          "invalid": {
            "type": "boolean",
            "default": "false",
            "description": "Show error styling on the fields."
          },
          "name": {
            "type": "string",
            "description": "Name prefix used for each <input> (rendered as `${name}-${index}`)."
          },
          "className": {
            "type": "string",
            "description": "Additional CSS class for the root."
          },
          "ariaLabel": {
            "type": "string",
            "default": "'Verification code'",
            "description": "Accessible name for the group."
          }
        }
      },
      "storyDir": "pin-input"
    },
    "PivotTable": {
      "name": "PivotTable",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React from 'react';\nimport { PivotTable } from '../../../components';\nimport type { PivotConfig } from '../../../components/pivot-table/pivot-table-types';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { currencyFormat, numberFormat, salesData } from './pivot-table-story-data';\n\nconst config: PivotConfig = {\n    rows: ['region'],\n    columns: [],\n    values: [\n        { field: 'revenue', label: 'Revenue', aggregateFunction: 'sum', format: currencyFormat },\n        { field: 'quantity', label: 'Quantity', aggregateFunction: 'sum', format: numberFormat },\n        { field: 'profit', label: 'Profit', aggregateFunction: 'sum', format: currencyFormat },\n    ],\n};\n\nconst code = `import { PivotTable } from 'fluxo-ui';\nimport type { PivotConfig } from 'fluxo-ui';\n\nconst config: PivotConfig = {\n    rows: ['region'],\n    columns: [],\n    values: [\n        { field: 'revenue', label: 'Revenue', aggregateFunction: 'sum', format: currencyFormat },\n        { field: 'quantity', label: 'Quantity', aggregateFunction: 'sum', format: numberFormat },\n        { field: 'profit', label: 'Profit', aggregateFunction: 'sum', format: currencyFormat },\n    ],\n};\n\n<PivotTable data={salesData} config={config} showToolbar />`;\n\nconst BasicUsage: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Simple Pivot Table\" description=\"Sales data pivoted by region showing revenue, quantity, and profit totals.\">\n            <PivotTable data={salesData} config={config} showToolbar />\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default BasicUsage;\n"
        },
        {
          "title": "ColumnPivot",
          "code": "import React from 'react';\nimport { PivotTable } from '../../../components';\nimport type { PivotConfig } from '../../../components/pivot-table/pivot-table-types';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { currencyFormat, salesData } from './pivot-table-story-data';\n\nconst config: PivotConfig = {\n    rows: ['region'],\n    columns: ['quarter'],\n    values: [{ field: 'revenue', label: 'Revenue', aggregateFunction: 'sum', format: currencyFormat }],\n};\n\nconst code = `import { PivotTable } from 'fluxo-ui';\nimport type { PivotConfig } from 'fluxo-ui';\n\nconst config: PivotConfig = {\n    rows: ['region'],\n    columns: ['quarter'],\n    values: [\n        { field: 'revenue', label: 'Revenue', aggregateFunction: 'sum', format: currencyFormat },\n    ],\n};\n\n<PivotTable\n    data={salesData}\n    config={config}\n    showGrandTotal\n    showColumnTotals\n    compact\n/>`;\n\nconst ColumnPivot: React.FC = () => (\n    <>\n        <ComponentDemo\n            title=\"Column Pivoting by Quarter\"\n            description=\"Revenue by region with quarterly columns. Each quarter becomes a column header, creating a cross-tabulation view.\"\n        >\n            <PivotTable data={salesData} config={config} showGrandTotal showColumnTotals compact />\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default ColumnPivot;\n"
        },
        {
          "title": "Filtering",
          "code": "import React, { useMemo, useState } from 'react';\nimport { Button, PivotTable } from '../../../components';\nimport type { PivotConfig, PivotFilter } from '../../../components/pivot-table/pivot-table-types';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { currencyFormat, numberFormat, salesData } from './pivot-table-story-data';\n\nconst regionOptions = ['All Regions', 'North America', 'Europe', 'Asia Pacific'] as const;\nconst categoryOptions = ['All Categories', 'Electronics', 'Accessories'] as const;\n\nconst code = `import { PivotTable } from 'fluxo-ui';\nimport type { PivotConfig, PivotFilter } from 'fluxo-ui';\n\nconst filters: PivotFilter[] = [\n    { field: 'region', operator: 'eq', value: 'Europe' },\n    { field: 'category', operator: 'eq', value: 'Electronics' },\n];\n\nconst config: PivotConfig = {\n    rows: ['country', 'product'],\n    columns: [],\n    values: [\n        { field: 'revenue', label: 'Revenue', aggregateFunction: 'sum', format: currencyFormat },\n        { field: 'quantity', label: 'Quantity', aggregateFunction: 'sum', format: numberFormat },\n        { field: 'profit', label: 'Profit', aggregateFunction: 'sum', format: currencyFormat },\n    ],\n    filters,\n};\n\n<PivotTable data={salesData} config={config} expandAll />`;\n\nconst Filtering: React.FC = () => {\n    const [selectedRegion, setSelectedRegion] = useState<string>('All Regions');\n    const [selectedCategory, setSelectedCategory] = useState<string>('All Categories');\n\n    const config: PivotConfig = useMemo(() => {\n        const filters: PivotFilter[] = [];\n\n        if (selectedRegion !== 'All Regions') {\n            filters.push({ field: 'region', operator: 'eq', value: selectedRegion });\n        }\n        if (selectedCategory !== 'All Categories') {\n            filters.push({ field: 'category', operator: 'eq', value: selectedCategory });\n        }\n\n        return {\n            rows: ['country', 'product'],\n            columns: [],\n            values: [\n                { field: 'revenue', label: 'Revenue', aggregateFunction: 'sum', format: currencyFormat },\n                { field: 'quantity', label: 'Quantity', aggregateFunction: 'sum', format: numberFormat },\n                { field: 'profit', label: 'Profit', aggregateFunction: 'sum', format: currencyFormat },\n            ],\n            filters,\n        };\n    }, [selectedRegion, selectedCategory]);\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Filtered Pivot Data\"\n                description=\"Apply filters to narrow pivot table data. Select a region and/or category to see filtered results.\"\n            >\n                <div className=\"flex flex-wrap gap-3 mb-4\">\n                    <div className=\"flex flex-wrap gap-2\">\n                        {regionOptions.map((region) => (\n                            <Button\n                                key={region}\n                                variant={selectedRegion === region ? 'primary' : 'default'}\n                                size=\"sm\"\n                                onClick={() => setSelectedRegion(region)}\n                            >\n                                {region}\n                            </Button>\n                        ))}\n                    </div>\n                    <div className=\"flex flex-wrap gap-2\">\n                        {categoryOptions.map((cat) => (\n                            <Button\n                                key={cat}\n                                variant={selectedCategory === cat ? 'primary' : 'default'}\n                                size=\"sm\"\n                                onClick={() => setSelectedCategory(cat)}\n                            >\n                                {cat}\n                            </Button>\n                        ))}\n                    </div>\n                </div>\n                <PivotTable data={salesData} config={config} expandAll showToolbar />\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default Filtering;\n"
        },
        {
          "title": "InteractiveDemo",
          "code": "import cn from 'classnames';\nimport React, { useState } from 'react';\nimport { PivotTable } from '../../../components';\nimport type { PivotConfig } from '../../../components/pivot-table/pivot-table-types';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\nimport { currencyFormat, salesData } from './pivot-table-story-data';\n\nconst code = `import { PivotTable } from 'fluxo-ui';\nimport type { PivotConfig, FieldDefinition, PivotPlugin } from 'fluxo-ui';\n\nconst [config, setConfig] = useState<PivotConfig>({\n  rows: ['region'],\n  columns: [],\n  values: [{ field: 'revenue', label: 'Revenue', aggregateFunction: 'sum' }],\n});\n\n<PivotTable\n  data={data}\n  config={config}\n  onConfigChange={setConfig}\n  showConfigPanel\n  editable\n  showToolbar\n  exportable\n  fieldDefinitions={fieldDefs}\n  plugins={myPlugins}\n  disabledFunctions={['product', 'variance']}\n/>`;\n\nconst InteractiveDemo: React.FC = () => {\n    const { isDark } = useStoryTheme();\n    const [config, setConfig] = useState<PivotConfig>({\n        rows: ['region', 'country'],\n        columns: [],\n        values: [\n            { field: 'revenue', label: 'Revenue', aggregateFunction: 'sum', format: currencyFormat },\n            { field: 'quantity', label: 'Qty', aggregateFunction: 'sum' },\n        ],\n    });\n    const [data, setData] = useState(salesData);\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Interactive Pivot\"\n                description=\"Drag fields between zones. Double-click leaf cells to edit. Change aggregation functions on value chips.\"\n            >\n                <div className={cn('rounded-lg overflow-hidden border', { 'border-white/10': isDark, 'border-gray-200': !isDark })}>\n                    <PivotTable\n                        data={data}\n                        config={config}\n                        onConfigChange={setConfig}\n                        onDataChange={(newData) => setData(newData as typeof salesData)}\n                        showConfigPanel\n                        configPanelPosition=\"left\"\n                        showToolbar\n                        editable\n                        exportable\n                        showGrandTotal\n                        showSubTotals\n                        expandAll\n                        height=\"400px\"\n                        fieldDefinitions={[\n                            { field: 'region', label: 'Region', dataType: 'string' },\n                            { field: 'country', label: 'Country', dataType: 'string' },\n                            { field: 'city', label: 'City', dataType: 'string' },\n                            { field: 'product', label: 'Product', dataType: 'string' },\n                            { field: 'category', label: 'Category', dataType: 'string' },\n                            { field: 'quarter', label: 'Quarter', dataType: 'string' },\n                            { field: 'salesperson', label: 'Salesperson', dataType: 'string' },\n                            { field: 'revenue', label: 'Revenue', dataType: 'number', editable: true },\n                            { field: 'quantity', label: 'Quantity', dataType: 'number', editable: true },\n                            { field: 'profit', label: 'Profit', dataType: 'number', editable: true },\n                        ]}\n                    />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default InteractiveDemo;\n"
        },
        {
          "title": "MultiLevelPivot",
          "code": "import React from 'react';\nimport { PivotTable } from '../../../components';\nimport type { PivotConfig } from '../../../components/pivot-table/pivot-table-types';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { currencyFormat, numberFormat, salesData } from './pivot-table-story-data';\n\nconst config: PivotConfig = {\n    rows: ['region', 'country', 'city'],\n    columns: [],\n    values: [\n        { field: 'revenue', label: 'Revenue', aggregateFunction: 'sum', format: currencyFormat },\n        { field: 'quantity', label: 'Quantity', aggregateFunction: 'sum', format: numberFormat },\n        { field: 'profit', label: 'Profit', aggregateFunction: 'sum', format: currencyFormat },\n    ],\n};\n\nconst code = `import { PivotTable } from 'fluxo-ui';\nimport type { PivotConfig } from 'fluxo-ui';\n\nconst config: PivotConfig = {\n    rows: ['region', 'country', 'city'],\n    columns: [],\n    values: [\n        { field: 'revenue', label: 'Revenue', aggregateFunction: 'sum', format: currencyFormat },\n        { field: 'quantity', label: 'Quantity', aggregateFunction: 'sum', format: numberFormat },\n        { field: 'profit', label: 'Profit', aggregateFunction: 'sum', format: currencyFormat },\n    ],\n};\n\n<PivotTable\n    data={salesData}\n    config={config}\n    expandAll\n    showSubTotals\n    showToolbar\n    bordered\n/>`;\n\nconst MultiLevelPivot: React.FC = () => (\n    <>\n        <ComponentDemo\n            title=\"Multi-Level Row Pivot\"\n            description=\"Three levels of row grouping: Region > Country > City. Use the toolbar to expand or collapse all rows.\"\n        >\n            <PivotTable data={salesData} config={config} expandAll showSubTotals showToolbar bordered />\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default MultiLevelPivot;\n"
        },
        {
          "title": "MultipleFunctions",
          "code": "import React from 'react';\nimport { PivotTable } from '../../../components';\nimport type { PivotConfig } from '../../../components/pivot-table/pivot-table-types';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { currencyFormat, decimalFormat, numberFormat, salesData } from './pivot-table-story-data';\n\nconst config: PivotConfig = {\n    rows: ['category'],\n    columns: [],\n    values: [\n        { field: 'revenue', label: 'Total Revenue (Sum)', aggregateFunction: 'sum', format: currencyFormat },\n        { field: 'revenue', label: 'Avg Revenue', aggregateFunction: 'average', format: currencyFormat },\n        { field: 'revenue', label: 'Min Revenue', aggregateFunction: 'min', format: currencyFormat },\n        { field: 'revenue', label: 'Max Revenue', aggregateFunction: 'max', format: currencyFormat },\n        { field: 'quantity', label: 'Orders (Count)', aggregateFunction: 'count', format: numberFormat },\n        { field: 'profit', label: 'Median Profit', aggregateFunction: 'median', format: currencyFormat },\n        { field: 'salesperson', label: 'Unique Sellers', aggregateFunction: 'distinctCount', format: decimalFormat },\n    ],\n};\n\nconst code = `import { PivotTable } from 'fluxo-ui';\nimport type { PivotConfig } from 'fluxo-ui';\n\nconst config: PivotConfig = {\n    rows: ['category'],\n    columns: [],\n    values: [\n        { field: 'revenue', label: 'Total Revenue (Sum)', aggregateFunction: 'sum', format: currencyFormat },\n        { field: 'revenue', label: 'Avg Revenue', aggregateFunction: 'average', format: currencyFormat },\n        { field: 'revenue', label: 'Min Revenue', aggregateFunction: 'min', format: currencyFormat },\n        { field: 'revenue', label: 'Max Revenue', aggregateFunction: 'max', format: currencyFormat },\n        { field: 'quantity', label: 'Orders (Count)', aggregateFunction: 'count', format: numberFormat },\n        { field: 'profit', label: 'Median Profit', aggregateFunction: 'median', format: currencyFormat },\n        { field: 'salesperson', label: 'Unique Sellers', aggregateFunction: 'distinctCount' },\n    ],\n};\n\n<PivotTable data={salesData} config={config} striped />`;\n\nconst MultipleFunctions: React.FC = () => (\n    <>\n        <ComponentDemo\n            title=\"Aggregate Functions\"\n            description=\"Demonstrates sum, average, min, max, count, median, and distinctCount aggregations on sales data by category.\"\n        >\n            <PivotTable data={salesData} config={config} striped />\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default MultipleFunctions;\n"
        }
      ],
      "props": {
        "pivotTableProps": {
          "data": {
            "type": "T[]",
            "required": true,
            "description": "Array of data objects to pivot."
          },
          "config": {
            "type": "PivotConfig",
            "required": true,
            "description": "Configuration with rows, columns, values, and optional filters."
          },
          "fieldDefinitions": {
            "type": "FieldDefinition[]",
            "description": "Defines field types, labels, editors, templates, and validators."
          },
          "onConfigChange": {
            "type": "(config: PivotConfig) => void",
            "description": "Called when user changes pivot configuration via drag-drop."
          },
          "onDataChange": {
            "type": "(data: T[], rowIndex, field, newValue) => void",
            "description": "Called after inline cell edits."
          },
          "showConfigPanel": {
            "type": "boolean",
            "default": "false",
            "description": "Show the interactive drag-and-drop configuration panel."
          },
          "configPanelPosition": {
            "type": "'left' | 'right' | 'top'",
            "default": "'left'",
            "description": "Position of the config panel."
          },
          "configPanelCollapsible": {
            "type": "boolean",
            "default": "true",
            "description": "Allow collapsing the config panel."
          },
          "editable": {
            "type": "boolean",
            "default": "false",
            "description": "Enable inline cell editing on double-click."
          },
          "onCellEdit": {
            "type": "(row, field, oldVal, newVal) => boolean | void",
            "description": "Validate or intercept cell edits. Return false to cancel."
          },
          "plugins": {
            "type": "PivotPlugin[]",
            "description": "Array of plugin objects for custom functions, renderers, and editors."
          },
          "disabledFunctions": {
            "type": "BuiltInAggregateFunction[]",
            "description": "Remove specific built-in aggregate functions."
          },
          "permissions": {
            "type": "PivotPermissions",
            "description": "Fine-grained control over what users can do (drag, edit, filter, export)."
          },
          "cellTemplate": {
            "type": "ComponentType<CellTemplateProps> | function",
            "description": "Global custom cell renderer for all value cells."
          },
          "headerTemplate": {
            "type": "(field, label) => ReactNode",
            "description": "Custom renderer for column headers."
          },
          "rowHeaderTemplate": {
            "type": "(label, depth, node) => ReactNode",
            "description": "Custom renderer for row headers."
          },
          "exportable": {
            "type": "boolean",
            "default": "false",
            "description": "Show CSV/JSON export buttons in toolbar."
          },
          "onExport": {
            "type": "(format: 'csv' | 'json') => void",
            "description": "Custom export handler."
          },
          "loading": {
            "type": "boolean",
            "default": "false",
            "description": "Show loading spinner."
          },
          "height": {
            "type": "string | number",
            "description": "Max height for scrollable area."
          },
          "expandAll": {
            "type": "boolean",
            "default": "false",
            "description": "Expand all row groups on initial render."
          },
          "showGrandTotal": {
            "type": "boolean",
            "default": "true",
            "description": "Show a grand total row at the bottom."
          },
          "showSubTotals": {
            "type": "boolean",
            "default": "true",
            "description": "Show subtotal rows for expanded groups."
          },
          "sortable": {
            "type": "boolean",
            "default": "true",
            "description": "Enable column header sorting."
          },
          "striped": {
            "type": "boolean",
            "default": "false",
            "description": "Apply alternating row backgrounds."
          },
          "bordered": {
            "type": "boolean",
            "default": "true",
            "description": "Show cell borders."
          },
          "compact": {
            "type": "boolean",
            "default": "false",
            "description": "Reduce cell padding for a denser layout."
          },
          "showToolbar": {
            "type": "boolean",
            "default": "false",
            "description": "Show toolbar with expand/collapse, export, and record count."
          }
        }
      },
      "storyDir": "pivot-table"
    },
    "PullToRefresh": {
      "name": "PullToRefresh",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React, { useCallback, useState } from 'react';\nimport { PullToRefresh } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { PullToRefresh } from 'fluxo-ui';\n\n<PullToRefresh onRefresh={async () => {\n    await fetchLatest();\n}}>\n    {/* scrollable content */}\n</PullToRefresh>`;\n\nconst wait = (ms: number) => new Promise<void>((r) => setTimeout(r, ms));\n\nconst BasicUsage: React.FC = () => {\n    const [items, setItems] = useState<string[]>(() => Array.from({ length: 20 }, (_, i) => `Item ${i + 1}`));\n    const [refreshes, setRefreshes] = useState(0);\n\n    const handleRefresh = useCallback(async () => {\n        await wait(900);\n        setRefreshes((n) => n + 1);\n        setItems((prev) => [`Refresh #${refreshes + 1}`, ...prev].slice(0, 20));\n    }, [refreshes]);\n\n    return (\n        <>\n            <ComponentDemo title=\"Pull down to refresh\" description=\"Touch the panel below, drag down past the threshold, and release. Promise-aware indicator stays visible until refresh resolves.\">\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16 }}>\n                    <div style={{\n                        height: 320,\n                        border: '1px solid var(--eui-border-subtle)',\n                        borderRadius: 8,\n                        overflow: 'hidden',\n                        background: 'var(--eui-bg-subtle)',\n                    }}>\n                        <PullToRefresh onRefresh={handleRefresh}>\n                            <ul style={{ listStyle: 'none', margin: 0, padding: '8px 16px' }}>\n                                {items.map((item) => (\n                                    <li key={item} style={{\n                                        padding: '12px 0',\n                                        borderBottom: '1px solid var(--eui-border-subtle)',\n                                        color: 'var(--eui-text)',\n                                    }}>{item}</li>\n                                ))}\n                            </ul>\n                        </PullToRefresh>\n                    </div>\n                    <div style={{\n                        padding: '10px 14px',\n                        background: 'var(--eui-bg-subtle)',\n                        border: '1px solid var(--eui-border-subtle)',\n                        borderRadius: 6,\n                        fontSize: 12,\n                        color: 'var(--eui-text-muted)',\n                    }}>\n                        Total refreshes: <strong style={{ color: 'var(--eui-text)' }}>{refreshes}</strong>\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\"><CodeBlock code={code} language=\"tsx\" /></div>\n        </>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "CustomThresholds",
          "code": "import React from 'react';\nimport { PullToRefresh } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst wait = (ms: number) => new Promise<void>((r) => setTimeout(r, ms));\n\nconst code = `<PullToRefresh\n    threshold={90}\n    maxPull={160}\n    refreshingText=\"Syncing your inbox…\"\n    pullingText=\"Keep pulling\"\n    releaseText=\"Release to sync\"\n    onRefresh={sync}\n>{...}</PullToRefresh>`;\n\nconst CustomThresholds: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Custom thresholds & labels\" description=\"Raise the threshold to require a longer pull, cap the maxPull travel, and customize each indicator label.\">\n            <div style={{\n                width: '100%',\n                height: 220,\n                border: '1px solid var(--eui-border-subtle)',\n                borderRadius: 8,\n                overflow: 'hidden',\n                background: 'var(--eui-bg-subtle)',\n            }}>\n                <PullToRefresh\n                    threshold={90}\n                    maxPull={160}\n                    refreshingText=\"Syncing your inbox…\"\n                    pullingText=\"Keep pulling\"\n                    releaseText=\"Release to sync\"\n                    onRefresh={() => wait(1400)}\n                >\n                    <div style={{ padding: 16, color: 'var(--eui-text)' }}>\n                        Pull at least 90px to trigger. Try a fast flick to see velocity-based dismissal.\n                    </div>\n                </PullToRefresh>\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\"><CodeBlock code={code} language=\"tsx\" /></div>\n    </>\n);\n\nexport default CustomThresholds;\n"
        },
        {
          "title": "Variants",
          "code": "import React from 'react';\nimport { PullToRefresh } from '../../../components';\nimport type { PullToRefreshVariant } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst wait = (ms: number) => new Promise<void>((r) => setTimeout(r, ms));\n\nconst variantCode = `<PullToRefresh variant=\"dots\" onRefresh={refresh}>\n    {/* scrollable content */}\n</PullToRefresh>`;\n\nconst variantList: { variant: PullToRefreshVariant; title: string; description: string }[] = [\n    { variant: 'spinner', title: 'Spinner (default)', description: 'A refresh icon that rotates with pull progress and spins while refreshing.' },\n    { variant: 'arrow', title: 'Arrow', description: 'An arrow that flips upside down once the threshold is reached.' },\n    { variant: 'dots', title: 'Dots', description: 'Three bouncing dots — minimal and unobtrusive.' },\n    { variant: 'minimal', title: 'Minimal', description: 'Just a thin progress bar with no text label.' },\n];\n\nconst VariantPanel: React.FC<{ variant: PullToRefreshVariant; title: string; description: string }> = ({ variant, title, description }) => (\n    <ComponentDemo title={title} description={description}>\n        <div style={{\n            width: '100%',\n            height: 200,\n            border: '1px solid var(--eui-border-subtle)',\n            borderRadius: 8,\n            overflow: 'hidden',\n            background: 'var(--eui-bg-subtle)',\n        }}>\n            <PullToRefresh variant={variant} onRefresh={() => wait(1200)}>\n                <div style={{ padding: 16, color: 'var(--eui-text-muted)' }}>\n                    Drag down inside this panel to trigger a 1.2s refresh using the <strong style={{ color: 'var(--eui-text)' }}>{variant}</strong> indicator.\n                </div>\n            </PullToRefresh>\n        </div>\n    </ComponentDemo>\n);\n\nconst Variants: React.FC = () => (\n    <>\n        {variantList.map((v) => (\n            <div key={v.variant} className=\"mb-4\">\n                <VariantPanel {...v} />\n            </div>\n        ))}\n        <CodeBlock code={variantCode} language=\"tsx\" />\n    </>\n);\n\nexport default Variants;\n"
        }
      ],
      "props": {
        "pullToRefreshProps": {
          "onRefresh": {
            "type": "() => void | Promise<void>",
            "required": true,
            "description": "Called when the user releases past the threshold. Return a Promise to keep the spinner visible until the work completes."
          },
          "children": {
            "type": "ReactNode",
            "required": true,
            "description": "Scrollable content to wrap."
          },
          "threshold": {
            "type": "number",
            "default": "64",
            "description": "Distance in pixels the user must pull before a refresh is triggered."
          },
          "maxPull": {
            "type": "number",
            "default": "120",
            "description": "Maximum visual pull distance (after drag resistance)."
          },
          "disabled": {
            "type": "boolean",
            "default": "false",
            "description": "Disable the gesture entirely."
          },
          "variant": {
            "type": "'spinner' | 'arrow' | 'dots' | 'minimal'",
            "default": "'spinner'",
            "description": "Indicator style. 'spinner' rotates with pull progress, 'arrow' flips on threshold, 'dots' shows three bouncing dots, 'minimal' shows a plain bar."
          },
          "refreshingText": {
            "type": "string",
            "default": "'Refreshing…'",
            "description": "Indicator label shown while the promise is pending."
          },
          "pullingText": {
            "type": "string",
            "default": "'Pull to refresh'",
            "description": "Indicator label shown while pulling but before threshold."
          },
          "releaseText": {
            "type": "string",
            "default": "'Release to refresh'",
            "description": "Indicator label shown once the threshold is reached."
          },
          "className": {
            "type": "string",
            "description": "Additional CSS class for the wrapper."
          },
          "scrollContainer": {
            "type": "HTMLElement | null",
            "description": "External scroll container to observe instead of the wrapper. Useful when the scrollable element lives below this wrapper."
          }
        }
      },
      "storyDir": "pull-to-refresh"
    },
    "QRCode": {
      "name": "QRCode",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React, { useState } from 'react';\nimport { QRCode } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { QRCode } from 'fluxo-ui';\n\n<QRCode value=\"https://fluxo-ui.utilsware.com/\" size={200} />`;\n\nconst valueLabelStyle: React.CSSProperties = {\n    fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Consolas, monospace',\n    fontSize: 11,\n    color: 'var(--eui-text)',\n    background: 'var(--eui-bg-subtle)',\n    border: '1px solid var(--eui-border-subtle)',\n    borderRadius: 4,\n    padding: '4px 8px',\n    maxWidth: 220,\n    textAlign: 'center',\n    overflow: 'hidden',\n    textOverflow: 'ellipsis',\n    whiteSpace: 'nowrap',\n};\n\nconst BasicUsage: React.FC = () => {\n    const [value, setValue] = useState('https://fluxo-ui.utilsware.com/');\n    return (\n        <>\n            <ComponentDemo\n                title=\"Default QR Code\"\n                description=\"Type any URL or text — the QR updates live so you can scan it from your phone camera.\"\n            >\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16, alignItems: 'center' }}>\n                    <QRCode value={value || ' '} size={240} />\n                    <div style={valueLabelStyle} title={value}>\n                        Encodes: {value || '(empty)'}\n                    </div>\n                    <div\n                        style={{\n                            padding: '12px 16px',\n                            background: 'var(--eui-bg-subtle)',\n                            border: '1px solid var(--eui-border-subtle)',\n                            borderRadius: 6,\n                            width: '100%',\n                            maxWidth: 520,\n                            display: 'flex',\n                            flexDirection: 'column',\n                            gap: 8,\n                        }}\n                    >\n                        <label htmlFor=\"qr-input\" style={{ fontSize: 12, color: 'var(--eui-text-muted)' }}>\n                            Encoded value · scan with your phone to verify\n                        </label>\n                        <input\n                            id=\"qr-input\"\n                            type=\"text\"\n                            value={value}\n                            onChange={(e) => setValue(e.target.value)}\n                            placeholder=\"https://example.com or any text\"\n                            style={{\n                                padding: '6px 10px',\n                                border: '1px solid var(--eui-border)',\n                                borderRadius: 4,\n                                background: 'var(--eui-bg)',\n                                color: 'var(--eui-text)',\n                                fontSize: 14,\n                                fontFamily: 'inherit',\n                            }}\n                        />\n                        <span style={{ fontSize: 11, color: 'var(--eui-text-muted)' }}>\n                            {value.length} characters · the QR re-encodes live\n                        </span>\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "Customization",
          "code": "import React, { useState } from 'react';\nimport { QRCode, QRCodeShape } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<QRCode\n  value=\"https://fluxo-ui.utilsware.com/components/qr-code\"\n  size={220}\n  foreground=\"#3b82f6\"\n  background=\"#ffffff\"\n  moduleShape=\"rounded\"\n  margin={4}\n/>`;\n\nconst valueLabelStyle: React.CSSProperties = {\n    fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Consolas, monospace',\n    fontSize: 11,\n    color: 'var(--eui-text)',\n    background: 'var(--eui-bg-subtle)',\n    border: '1px solid var(--eui-border-subtle)',\n    borderRadius: 4,\n    padding: '4px 8px',\n    maxWidth: 320,\n    textAlign: 'center',\n    overflow: 'hidden',\n    textOverflow: 'ellipsis',\n    whiteSpace: 'nowrap',\n};\n\nconst customizationValue = 'https://fluxo-ui.utilsware.com/components/qr-code';\n\nconst Customization: React.FC = () => {\n    const [shape, setShape] = useState<QRCodeShape>('rounded');\n    const [foreground, setForeground] = useState('#3b82f6');\n    const [background, setBackground] = useState('#ffffff');\n    const [size, setSize] = useState(220);\n    const [margin, setMargin] = useState(4);\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Color & Size Controls\"\n                description=\"Tune foreground, background, module shape, size, and quiet zone margin.\"\n            >\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16, alignItems: 'center' }}>\n                    <QRCode\n                        value={customizationValue}\n                        size={size}\n                        foreground={foreground}\n                        background={background}\n                        moduleShape={shape}\n                        margin={margin}\n                    />\n                    <div style={valueLabelStyle} title={customizationValue}>\n                        Encodes: {customizationValue}\n                    </div>\n                    <div\n                        style={{\n                            display: 'grid',\n                            gridTemplateColumns: 'auto 1fr auto',\n                            gap: 12,\n                            alignItems: 'center',\n                            padding: '12px 16px',\n                            background: 'var(--eui-bg-subtle)',\n                            border: '1px solid var(--eui-border-subtle)',\n                            borderRadius: 6,\n                            width: '100%',\n                            maxWidth: 520,\n                            fontSize: 13,\n                        }}\n                    >\n                        <label htmlFor=\"qr-shape\">Shape</label>\n                        <select\n                            id=\"qr-shape\"\n                            value={shape}\n                            onChange={(e) => setShape(e.target.value as QRCodeShape)}\n                            style={{ gridColumn: '2 / span 2', padding: '4px 8px', borderRadius: 4 }}\n                        >\n                            <option value=\"square\">square</option>\n                            <option value=\"rounded\">rounded</option>\n                            <option value=\"dots\">dots</option>\n                        </select>\n\n                        <label htmlFor=\"qr-fg\">Foreground</label>\n                        <input id=\"qr-fg\" type=\"color\" value={foreground} onChange={(e) => setForeground(e.target.value)} />\n                        <span>{foreground}</span>\n\n                        <label htmlFor=\"qr-bg\">Background</label>\n                        <input id=\"qr-bg\" type=\"color\" value={background} onChange={(e) => setBackground(e.target.value)} />\n                        <span>{background}</span>\n\n                        <label htmlFor=\"qr-size\">Size</label>\n                        <input\n                            id=\"qr-size\"\n                            type=\"range\"\n                            min={120}\n                            max={360}\n                            step={4}\n                            value={size}\n                            onChange={(e) => setSize(Number(e.target.value))}\n                        />\n                        <span>{size}px</span>\n\n                        <label htmlFor=\"qr-margin\">Margin</label>\n                        <input\n                            id=\"qr-margin\"\n                            type=\"range\"\n                            min={0}\n                            max={10}\n                            step={1}\n                            value={margin}\n                            onChange={(e) => setMargin(Number(e.target.value))}\n                        />\n                        <span>{margin}</span>\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default Customization;\n"
        },
        {
          "title": "Download",
          "code": "import React, { useRef } from 'react';\nimport { Button, QRCode } from '../../../components';\nimport type { QRCodeHandle } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst downloadValue = 'BEGIN:VCARD\\nVERSION:3.0\\nFN:Fluxo UI\\nURL:https://fluxo-ui.utilsware.com\\nEMAIL:hello@fluxo-ui.dev\\nEND:VCARD';\n\nconst code = `import { useRef } from 'react';\nimport { Button, QRCode } from 'fluxo-ui';\nimport type { QRCodeHandle } from 'fluxo-ui';\n\nfunction Example() {\n    const qrRef = useRef<QRCodeHandle>(null);\n    const value = \\`${downloadValue}\\`;\n\n    return (\n        <>\n            <QRCode ref={qrRef} value={value} size={240} />\n            <Button onClick={() => qrRef.current?.download({ format: 'png', fileName: 'fluxo-vcard', scale: 4 })}>\n                Download PNG\n            </Button>\n            <Button onClick={() => qrRef.current?.download({ format: 'svg', fileName: 'fluxo-vcard' })}>\n                Download SVG\n            </Button>\n        </>\n    );\n}`;\n\nconst valueLabelStyle: React.CSSProperties = {\n    fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Consolas, monospace',\n    fontSize: 11,\n    color: 'var(--eui-text)',\n    background: 'var(--eui-bg-subtle)',\n    border: '1px solid var(--eui-border-subtle)',\n    borderRadius: 4,\n    padding: '8px 10px',\n    maxWidth: 360,\n    whiteSpace: 'pre-wrap',\n    wordBreak: 'break-all',\n};\n\nconst Download: React.FC = () => {\n    const qrRef = useRef<QRCodeHandle>(null);\n\n    const handleDownload = (format: 'png' | 'svg' | 'jpeg') => {\n        qrRef.current?.download({ format, fileName: 'fluxo-vcard', scale: 4 }).catch(() => {});\n    };\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Download as image\"\n                description=\"Use a ref to call download() — supports PNG, JPEG, and SVG. PNG/JPEG accept a scale factor for high-DPI exports. This example encodes a vCard so scanning adds the contact straight to your phone.\"\n            >\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16, alignItems: 'center' }}>\n                    <QRCode ref={qrRef} value={downloadValue} size={240} />\n                    <div style={valueLabelStyle}>\n                        Encodes vCard:\n                        {'\\n'}\n                        {downloadValue}\n                    </div>\n                    <div\n                        style={{\n                            padding: '12px 16px',\n                            background: 'var(--eui-bg-subtle)',\n                            border: '1px solid var(--eui-border-subtle)',\n                            borderRadius: 6,\n                            display: 'flex',\n                            flexWrap: 'wrap',\n                            gap: 8,\n                            justifyContent: 'center',\n                        }}\n                    >\n                        <Button variant=\"primary\" onClick={() => handleDownload('png')}>Download PNG</Button>\n                        <Button variant=\"secondary\" onClick={() => handleDownload('svg')}>Download SVG</Button>\n                        <Button variant=\"secondary\" onClick={() => handleDownload('jpeg')}>Download JPEG</Button>\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default Download;\n"
        },
        {
          "title": "ErrorCorrection",
          "code": "import React from 'react';\nimport { QRCode } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<QRCode value=\"https://news.ycombinator.com\" errorCorrection=\"L\" />\n<QRCode value=\"https://github.com/fluxo-ui\" errorCorrection=\"M\" />\n<QRCode value=\"https://en.wikipedia.org/wiki/QR_code\" errorCorrection=\"Q\" />\n<QRCode value=\"https://fluxo-ui.utilsware.com/?ref=docs\" errorCorrection=\"H\" />`;\n\nconst levels: { level: 'L' | 'M' | 'Q' | 'H'; recovery: number; value: string }[] = [\n    { level: 'L', recovery: 7, value: 'https://news.ycombinator.com' },\n    { level: 'M', recovery: 15, value: 'https://github.com/fluxo-ui' },\n    { level: 'Q', recovery: 25, value: 'https://en.wikipedia.org/wiki/QR_code' },\n    { level: 'H', recovery: 30, value: 'https://fluxo-ui.utilsware.com/?ref=docs' },\n];\n\nconst valueLabelStyle: React.CSSProperties = {\n    fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Consolas, monospace',\n    fontSize: 11,\n    color: 'var(--eui-text)',\n    background: 'var(--eui-bg-subtle)',\n    border: '1px solid var(--eui-border-subtle)',\n    borderRadius: 4,\n    padding: '4px 8px',\n    maxWidth: 180,\n    textAlign: 'center',\n    overflow: 'hidden',\n    textOverflow: 'ellipsis',\n    whiteSpace: 'nowrap',\n};\n\nconst ErrorCorrection: React.FC = () => (\n    <>\n        <ComponentDemo\n            title=\"Error Correction Levels\"\n            description=\"Higher levels add redundancy so the code stays scannable when partially obscured. Each example encodes a different URL.\"\n        >\n            <div style={{ display: 'flex', gap: 24, flexWrap: 'wrap', justifyContent: 'center' }}>\n                {levels.map(({ level, recovery, value }) => (\n                    <div key={level} style={{ display: 'flex', flexDirection: 'column', gap: 8, alignItems: 'center' }}>\n                        <QRCode value={value} size={160} errorCorrection={level} />\n                        <span style={{ fontSize: 12, color: 'var(--eui-text-muted)', fontWeight: 600 }}>\n                            Level {level} ({recovery}% recovery)\n                        </span>\n                        <div style={valueLabelStyle} title={value}>\n                            {value}\n                        </div>\n                    </div>\n                ))}\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default ErrorCorrection;\n"
        },
        {
          "title": "Shapes",
          "code": "import React from 'react';\nimport { QRCode } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<QRCode value=\"https://example.com\" moduleShape=\"square\" />\n<QRCode value=\"mailto:hello@fluxo-ui.dev\" moduleShape=\"rounded\" />\n<QRCode value=\"tel:+1-555-867-5309\" moduleShape=\"dots\" />`;\n\nconst shapes: { shape: 'square' | 'rounded' | 'dots'; value: string }[] = [\n    { shape: 'square', value: 'https://example.com' },\n    { shape: 'rounded', value: 'mailto:hello@fluxo-ui.dev' },\n    { shape: 'dots', value: 'tel:+1-555-867-5309' },\n];\n\nconst valueLabelStyle: React.CSSProperties = {\n    fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Consolas, monospace',\n    fontSize: 11,\n    color: 'var(--eui-text)',\n    background: 'var(--eui-bg-subtle)',\n    border: '1px solid var(--eui-border-subtle)',\n    borderRadius: 4,\n    padding: '4px 8px',\n    maxWidth: 180,\n    textAlign: 'center',\n    overflow: 'hidden',\n    textOverflow: 'ellipsis',\n    whiteSpace: 'nowrap',\n};\n\nconst Shapes: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Module Shapes\" description=\"Square (default), rounded, or dotted modules. Each example encodes a different value.\">\n            <div style={{ display: 'flex', gap: 24, flexWrap: 'wrap', justifyContent: 'center' }}>\n                {shapes.map(({ shape, value }) => (\n                    <div key={shape} style={{ display: 'flex', flexDirection: 'column', gap: 8, alignItems: 'center' }}>\n                        <QRCode value={value} size={160} moduleShape={shape} />\n                        <span style={{ fontSize: 12, color: 'var(--eui-text-muted)', fontWeight: 600 }}>{shape}</span>\n                        <div style={valueLabelStyle} title={value}>\n                            {value}\n                        </div>\n                    </div>\n                ))}\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default Shapes;\n"
        },
        {
          "title": "WithLogo",
          "code": "import React from 'react';\nimport { QRCode } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<QRCode\n  value=\"https://fluxo-ui.utilsware.com/components/qr-code\"\n  size={240}\n  moduleShape=\"rounded\"\n  logo={{ src: '/logo.svg', size: 48, padding: 6, rounded: true }}\n/>\n<QRCode\n  value=\"WIFI:T:WPA;S:FluxoGuest;P:welcome2025;;\"\n  size={240}\n  moduleShape=\"dots\"\n  foreground=\"#7c3aed\"\n  logo={{ src: '/logo.svg', size: 56, padding: 8, rounded: true }}\n/>`;\n\nconst valueLabelStyle: React.CSSProperties = {\n    fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Consolas, monospace',\n    fontSize: 11,\n    color: 'var(--eui-text)',\n    background: 'var(--eui-bg-subtle)',\n    border: '1px solid var(--eui-border-subtle)',\n    borderRadius: 4,\n    padding: '4px 8px',\n    maxWidth: 240,\n    textAlign: 'center',\n    overflow: 'hidden',\n    textOverflow: 'ellipsis',\n    whiteSpace: 'nowrap',\n};\n\nconst examples = [\n    {\n        value: 'https://fluxo-ui.utilsware.com/components/qr-code',\n        label: 'Docs link · rounded',\n        shape: 'rounded' as const,\n        logoSize: 48,\n        padding: 6,\n        foreground: undefined,\n    },\n    {\n        value: 'WIFI:T:WPA;S:FluxoGuest;P:welcome2025;;',\n        label: 'Wi-Fi credentials · dots',\n        shape: 'dots' as const,\n        logoSize: 56,\n        padding: 8,\n        foreground: '#7c3aed',\n    },\n];\n\nconst WithLogo: React.FC = () => (\n    <>\n        <ComponentDemo\n            title=\"Logo Overlay\"\n            description=\"When a logo is supplied, errorCorrection auto-bumps to 'H' so the code stays scannable. Each example encodes a different payload.\"\n        >\n            <div style={{ display: 'flex', gap: 32, justifyContent: 'center', flexWrap: 'wrap' }}>\n                {examples.map((ex) => (\n                    <div key={ex.label} style={{ display: 'flex', flexDirection: 'column', gap: 8, alignItems: 'center' }}>\n                        <QRCode\n                            value={ex.value}\n                            size={240}\n                            moduleShape={ex.shape}\n                            foreground={ex.foreground}\n                            logo={{ src: '/logo.svg', size: ex.logoSize, padding: ex.padding, rounded: true }}\n                        />\n                        <span style={{ fontSize: 12, color: 'var(--eui-text-muted)', fontWeight: 600 }}>{ex.label}</span>\n                        <div style={valueLabelStyle} title={ex.value}>\n                            {ex.value}\n                        </div>\n                    </div>\n                ))}\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default WithLogo;\n"
        }
      ],
      "props": {
        "qrCodeProps": {
          "value": {
            "type": "string",
            "required": true,
            "description": "Data to encode (URL, text, vCard, etc.)"
          },
          "size": {
            "type": "number",
            "default": "160",
            "description": "Output pixel size of the QR code (square)"
          },
          "errorCorrection": {
            "type": "'L' | 'M' | 'Q' | 'H'",
            "default": "'M'",
            "description": "Error correction level. Auto-bumped to 'H' when a logo is provided"
          },
          "margin": {
            "type": "number",
            "default": "4",
            "description": "Quiet-zone width in modules (≥ 4 recommended)"
          },
          "foreground": {
            "type": "string",
            "default": "'#000000'",
            "description": "Color of filled modules. Default is black for maximum scannability — use a dark hex/named color when overriding (CSS variables that flip with dark mode are NOT recommended, as most phone scanners reject light-on-dark QR codes)"
          },
          "background": {
            "type": "string",
            "default": "'#ffffff'",
            "description": "Color of the quiet zone and gaps. Default is white for maximum scannability. Use 'transparent' to omit"
          },
          "moduleShape": {
            "type": "'square' | 'dots' | 'rounded'",
            "default": "'square'",
            "description": "Shape of each module"
          },
          "logo": {
            "type": "{ src: string; size?: number; padding?: number; rounded?: boolean }",
            "description": "Optional centered logo overlay"
          },
          "onError": {
            "type": "(err: Error) => void",
            "description": "Fired when input is too long for the chosen error-correction level"
          },
          "id": {
            "type": "string",
            "description": "HTML id attribute"
          },
          "className": {
            "type": "string",
            "description": "Additional CSS classes"
          },
          "alt": {
            "type": "string",
            "description": "Accessible label (defaults to the value, truncated if long)"
          }
        }
      },
      "storyDir": "qr-code"
    },
    "QrScanner": {
      "name": "QrScanner",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React, { useState } from 'react';\nimport { QrScanner } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { QrScanner } from 'fluxo-ui';\n\n<QrScanner\n  onScan={(value) => console.log('Decoded:', value)}\n  onError={(err) => console.error(err)}\n/>`;\n\nconst readoutStyle: React.CSSProperties = {\n    padding: '12px 16px',\n    background: 'var(--eui-bg-subtle)',\n    border: '1px solid var(--eui-border-subtle)',\n    borderRadius: 6,\n    width: '100%',\n    maxWidth: 520,\n    color: 'var(--eui-text)',\n    fontSize: 13,\n    wordBreak: 'break-all',\n    minHeight: 56,\n    display: 'flex',\n    flexDirection: 'column',\n    gap: 4,\n};\n\nconst BasicUsage: React.FC = () => {\n    const [lastValue, setLastValue] = useState<string | null>(null);\n    const [errorText, setErrorText] = useState<string | null>(null);\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Default Scanner\"\n                description=\"Click Start scanning, point your camera at any QR code, and the decoded value appears below. Uses the native BarcodeDetector API — no third-party dependency.\"\n            >\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16, alignItems: 'center' }}>\n                    <div style={{ width: '100%', maxWidth: 360 }}>\n                        <QrScanner\n                            onScan={(value) => {\n                                setLastValue(value);\n                                setErrorText(null);\n                            }}\n                            onError={(err) => setErrorText(err.message)}\n                        />\n                    </div>\n                    <div style={readoutStyle} aria-live=\"polite\">\n                        <span style={{ fontSize: 11, color: 'var(--eui-text-muted)' }}>\n                            Last decoded value\n                        </span>\n                        <strong style={{ fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Consolas, monospace', fontSize: 13 }}>\n                            {lastValue ?? '— nothing scanned yet —'}\n                        </strong>\n                        {errorText && (\n                            <small style={{ color: '#ef4444' }}>Error: {errorText}</small>\n                        )}\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "ContinuousScan",
          "code": "import React, { useState } from 'react';\nimport { QrScanner } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<QrScanner\n  continuous\n  onScan={(value) => setHistory((h) => [value, ...h])}\n/>`;\n\nconst listStyle: React.CSSProperties = {\n    padding: '12px 16px',\n    background: 'var(--eui-bg-subtle)',\n    border: '1px solid var(--eui-border-subtle)',\n    borderRadius: 6,\n    width: '100%',\n    maxWidth: 520,\n    color: 'var(--eui-text)',\n    fontSize: 13,\n    minHeight: 80,\n    display: 'flex',\n    flexDirection: 'column',\n    gap: 6,\n};\n\nconst ContinuousScan: React.FC = () => {\n    const [history, setHistory] = useState<string[]>([]);\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Continuous Mode\"\n                description=\"With continuous=true, the scanner keeps reading after each successful detection — useful for batch entry. Duplicate codes are debounced for ~1.5 seconds.\"\n            >\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16, alignItems: 'center' }}>\n                    <div style={{ width: '100%', maxWidth: 360 }}>\n                        <QrScanner\n                            continuous\n                            onScan={(value) => setHistory((h) => [value, ...h].slice(0, 8))}\n                        />\n                    </div>\n                    <div style={listStyle} aria-live=\"polite\">\n                        <span style={{ fontSize: 11, color: 'var(--eui-text-muted)' }}>\n                            Scan history ({history.length})\n                        </span>\n                        {history.length === 0 ? (\n                            <em style={{ color: 'var(--eui-text-muted)', fontSize: 12 }}>\n                                No scans yet — start the scanner and aim at QR codes.\n                            </em>\n                        ) : (\n                            history.map((value, index) => (\n                                <code\n                                    key={`${value}-${index}`}\n                                    style={{\n                                        fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Consolas, monospace',\n                                        fontSize: 12,\n                                        background: 'var(--eui-bg)',\n                                        border: '1px solid var(--eui-border-subtle)',\n                                        borderRadius: 4,\n                                        padding: '4px 8px',\n                                        wordBreak: 'break-all',\n                                    }}\n                                >\n                                    {value}\n                                </code>\n                            ))\n                        )}\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default ContinuousScan;\n"
        },
        {
          "title": "Customization",
          "code": "import React, { useState } from 'react';\nimport { QrScanner } from '../../../components';\nimport type { QrScannerProps } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<QrScanner\n  overlay=\"frame\"\n  aspectRatio={1.333}\n  facingMode=\"environment\"\n  showTorchToggle\n  showCameraSwitch\n  onScan={handleScan}\n/>`;\n\nconst controlsStyle: React.CSSProperties = {\n    display: 'grid',\n    gridTemplateColumns: 'auto 1fr',\n    gap: 10,\n    alignItems: 'center',\n    padding: '12px 16px',\n    background: 'var(--eui-bg-subtle)',\n    border: '1px solid var(--eui-border-subtle)',\n    borderRadius: 6,\n    width: '100%',\n    maxWidth: 520,\n    fontSize: 13,\n};\n\nconst readoutStyle: React.CSSProperties = {\n    padding: '12px 16px',\n    background: 'var(--eui-bg-subtle)',\n    border: '1px solid var(--eui-border-subtle)',\n    borderRadius: 6,\n    width: '100%',\n    maxWidth: 520,\n    color: 'var(--eui-text)',\n    fontSize: 13,\n};\n\nconst Customization: React.FC = () => {\n    const [overlay, setOverlay] = useState<NonNullable<QrScannerProps['overlay']>>('mask');\n    const [aspectRatio, setAspectRatio] = useState(1);\n    const [facingMode, setFacingMode] = useState<NonNullable<QrScannerProps['facingMode']>>('environment');\n    const [lastValue, setLastValue] = useState<string | null>(null);\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Overlay & Aspect Ratio\"\n                description=\"Switch between the dimmed mask and bracket-only frame overlays, change aspect ratio, and pick the front or rear camera.\"\n            >\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16, alignItems: 'center' }}>\n                    <div style={{ width: '100%', maxWidth: 420 }}>\n                        <QrScanner\n                            overlay={overlay}\n                            aspectRatio={aspectRatio}\n                            facingMode={facingMode}\n                            onScan={(value) => setLastValue(value)}\n                        />\n                    </div>\n                    <div style={controlsStyle}>\n                        <label htmlFor=\"qr-overlay\">Overlay</label>\n                        <select\n                            id=\"qr-overlay\"\n                            value={overlay}\n                            onChange={(e) => setOverlay(e.target.value as NonNullable<QrScannerProps['overlay']>)}\n                            style={{ padding: '4px 8px', borderRadius: 4 }}\n                        >\n                            <option value=\"mask\">mask</option>\n                            <option value=\"frame\">frame</option>\n                            <option value=\"none\">none</option>\n                        </select>\n\n                        <label htmlFor=\"qr-ratio\">Aspect ratio</label>\n                        <select\n                            id=\"qr-ratio\"\n                            value={aspectRatio}\n                            onChange={(e) => setAspectRatio(Number(e.target.value))}\n                            style={{ padding: '4px 8px', borderRadius: 4 }}\n                        >\n                            <option value={1}>1 : 1</option>\n                            <option value={1.333}>4 : 3</option>\n                            <option value={1.777}>16 : 9</option>\n                            <option value={0.75}>3 : 4 (portrait)</option>\n                        </select>\n\n                        <label htmlFor=\"qr-facing\">Camera</label>\n                        <select\n                            id=\"qr-facing\"\n                            value={facingMode}\n                            onChange={(e) => setFacingMode(e.target.value as NonNullable<QrScannerProps['facingMode']>)}\n                            style={{ padding: '4px 8px', borderRadius: 4 }}\n                        >\n                            <option value=\"environment\">Rear (environment)</option>\n                            <option value=\"user\">Front (user)</option>\n                        </select>\n                    </div>\n                    <div style={readoutStyle} aria-live=\"polite\">\n                        <span style={{ fontSize: 11, color: 'var(--eui-text-muted)' }}>Last decoded value</span>\n                        <div\n                            style={{\n                                fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Consolas, monospace',\n                                fontSize: 13,\n                                wordBreak: 'break-all',\n                                marginTop: 4,\n                            }}\n                        >\n                            {lastValue ?? '—'}\n                        </div>\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default Customization;\n"
        },
        {
          "title": "ImperativeApi",
          "code": "import React, { useRef, useState } from 'react';\nimport { QrScanner } from '../../../components';\nimport type { QrScannerHandle } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { scanQrCodeOnce } from 'fluxo-ui/utils';\n\n// Lower-level utility — bring your own video element\nconst value = await scanQrCodeOnce({ video: videoRef.current });\n\n// Or drive the component imperatively\nconst ref = useRef<QrScannerHandle>(null);\nref.current?.start();\nref.current?.stop();`;\n\nconst buttonRowStyle: React.CSSProperties = {\n    display: 'flex',\n    gap: 8,\n    flexWrap: 'wrap',\n    padding: '12px 16px',\n    background: 'var(--eui-bg-subtle)',\n    border: '1px solid var(--eui-border-subtle)',\n    borderRadius: 6,\n    width: '100%',\n    maxWidth: 520,\n};\n\nconst buttonStyle: React.CSSProperties = {\n    padding: '8px 14px',\n    border: '1px solid var(--eui-border)',\n    borderRadius: 4,\n    background: 'var(--eui-bg)',\n    color: 'var(--eui-text)',\n    cursor: 'pointer',\n    fontSize: 13,\n    fontFamily: 'inherit',\n    minHeight: 36,\n};\n\nconst ImperativeApi: React.FC = () => {\n    const ref = useRef<QrScannerHandle>(null);\n    const [lastValue, setLastValue] = useState<string | null>(null);\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Imperative Control\"\n                description=\"Use the ref handle to start/stop the scanner from outside the component, or call the lower-level scanQrCodeOnce utility directly with your own video element.\"\n            >\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16, alignItems: 'center' }}>\n                    <div style={{ width: '100%', maxWidth: 360 }}>\n                        <QrScanner ref={ref} onScan={(value) => setLastValue(value)} />\n                    </div>\n                    <div style={buttonRowStyle}>\n                        <button type=\"button\" style={buttonStyle} onClick={() => ref.current?.start()}>\n                            ref.start()\n                        </button>\n                        <button type=\"button\" style={buttonStyle} onClick={() => ref.current?.stop()}>\n                            ref.stop()\n                        </button>\n                        <span style={{ marginLeft: 'auto', fontSize: 12, color: 'var(--eui-text-muted)', alignSelf: 'center' }}>\n                            Last: {lastValue ?? '—'}\n                        </span>\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default ImperativeApi;\n"
        }
      ],
      "props": {
        "qrScannerProps": {
          "onScan": {
            "type": "(value: string) => void",
            "required": true,
            "description": "Called with the decoded string when a QR code is recognized"
          },
          "onError": {
            "type": "(error: Error) => void",
            "description": "Called when the camera fails or a decode error occurs"
          },
          "facingMode": {
            "type": "'environment' | 'user'",
            "default": "'environment'",
            "description": "Preferred camera direction. 'environment' selects the rear camera on mobile"
          },
          "formats": {
            "type": "string[]",
            "default": "['qr_code']",
            "description": "BarcodeDetector formats to recognize. Use ['qr_code'] for QR only, or include other 2D/1D formats supported by the browser"
          },
          "continuous": {
            "type": "boolean",
            "default": "false",
            "description": "When true, keeps scanning after each detected code (useful for batch workflows). When false, stops after the first detection"
          },
          "autoStart": {
            "type": "boolean",
            "default": "false",
            "description": "When true, requests the camera and starts scanning on mount. Note: iOS Safari may require a user gesture, so a Start button is the safer default"
          },
          "showTorchToggle": {
            "type": "boolean",
            "default": "true",
            "description": "Show the flashlight (torch) toggle button when supported by the device"
          },
          "showCameraSwitch": {
            "type": "boolean",
            "default": "true",
            "description": "Show the front/rear camera switch button when more than one video input is available"
          },
          "overlay": {
            "type": "'frame' | 'mask' | 'none'",
            "default": "'mask'",
            "description": "Visual overlay style. 'mask' dims the area around the framing reticle, 'frame' shows just the corner brackets, 'none' hides the overlay"
          },
          "width": {
            "type": "number | string",
            "default": "'100%'",
            "description": "Outer container width. Accepts CSS units (e.g. 320, '100%', '24rem')"
          },
          "height": {
            "type": "number | string",
            "description": "Outer container height. If omitted, the container uses aspectRatio to size itself"
          },
          "aspectRatio": {
            "type": "number",
            "default": "1",
            "description": "Aspect ratio used when height is not provided. 1 = square, 1.333 = 4:3, 1.777 = 16:9"
          },
          "scanIntervalMs": {
            "type": "number",
            "default": "200",
            "description": "Polling interval in milliseconds. Lower values = faster detection at higher CPU/battery cost"
          },
          "pauseAfterScan": {
            "type": "boolean",
            "default": "true",
            "description": "When continuous=false, stop the camera and return to idle after the first successful scan"
          },
          "unsupportedMessage": {
            "type": "ReactNode",
            "description": "Custom message shown when the browser does not support BarcodeDetector"
          },
          "deniedMessage": {
            "type": "ReactNode",
            "description": "Custom message shown when the user denies camera permission"
          },
          "startLabel": {
            "type": "ReactNode",
            "default": "'Start scanning'",
            "description": "Label for the start button"
          },
          "id": {
            "type": "string",
            "description": "HTML id attribute"
          },
          "className": {
            "type": "string",
            "description": "Additional CSS classes"
          },
          "ariaLabel": {
            "type": "string",
            "default": "'QR code scanner'",
            "description": "Accessible label for the scanner region"
          }
        }
      },
      "storyDir": "qr-scanner"
    },
    "Rating": {
      "name": "Rating",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React, { useState } from 'react';\nimport { Rating } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { Rating } from 'fluxo-ui';\n\nconst [value, setValue] = useState(3);\n\n<Rating value={value} onChange={setValue} />\n\n<Rating defaultValue={4} showValue />\n\n<Rating defaultValue={3.5} precision={0.5} showValue />`;\n\nconst BasicUsage: React.FC = () => {\n    const [value, setValue] = useState(3);\n\n    return (\n        <>\n            <ComponentDemo title=\"Default Rating\" description=\"Click a star to set the value. Click the same star again to clear.\">\n                <div className=\"space-y-6\">\n                    <div>\n                        <div className=\"text-sm mb-2 opacity-70\">Controlled (value: {value})</div>\n                        <Rating value={value} onChange={setValue} />\n                    </div>\n                    <div>\n                        <div className=\"text-sm mb-2 opacity-70\">Uncontrolled with value display</div>\n                        <Rating defaultValue={4} showValue />\n                    </div>\n                    <div>\n                        <div className=\"text-sm mb-2 opacity-70\">Half-star precision</div>\n                        <Rating defaultValue={3.5} precision={0.5} showValue />\n                    </div>\n                    <div>\n                        <div className=\"text-sm mb-2 opacity-70\">Read-only</div>\n                        <Rating value={4} readOnly showValue />\n                    </div>\n                    <div>\n                        <div className=\"text-sm mb-2 opacity-70\">Disabled</div>\n                        <Rating value={3} disabled />\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "Labels",
          "code": "import React from 'react';\nimport { Rating } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst tooltips = ['Terrible', 'Bad', 'Okay', 'Good', 'Excellent'];\n\nconst code = `<Rating\n  tooltips={['Terrible', 'Bad', 'Okay', 'Good', 'Excellent']}\n  labels={['Terrible', 'Bad', 'Okay', 'Good', 'Excellent']}\n  defaultValue={4}\n/>`;\n\nconst Labels: React.FC = () => (\n    <>\n        <ComponentDemo\n            title=\"Tooltips & Labels\"\n            description=\"Show a dynamic label based on the current hover or selection, plus per-star tooltips.\"\n        >\n            <div className=\"space-y-6\">\n                <div>\n                    <div className=\"text-sm mb-2 opacity-70\">With tooltips (hover a star)</div>\n                    <Rating tooltips={tooltips} defaultValue={3} />\n                </div>\n                <div>\n                    <div className=\"text-sm mb-2 opacity-70\">With dynamic label</div>\n                    <Rating tooltips={tooltips} labels={tooltips} defaultValue={4} />\n                </div>\n                <div>\n                    <div className=\"text-sm mb-2 opacity-70\">Custom count (10 stars)</div>\n                    <Rating count={10} defaultValue={7} showValue />\n                </div>\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default Labels;\n"
        },
        {
          "title": "Precision",
          "code": "import React, { useState } from 'react';\nimport { Rating } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<Rating precision={1} defaultValue={3} showValue />\n\n<Rating precision={0.5} defaultValue={3.5} showValue />\n\n<Rating precision={0.1} defaultValue={3.7} showValue />`;\n\nconst Precision: React.FC = () => {\n    const [halfValue, setHalfValue] = useState(3.5);\n    const [decValue, setDecValue] = useState(3.7);\n\n    return (\n        <>\n            <ComponentDemo title=\"Precision\" description=\"Click anywhere on a star to set fractional values. Supports 1, 0.5, or 0.1 precision.\">\n                <div className=\"space-y-6\">\n                    <div>\n                        <div className=\"text-sm mb-2 opacity-70\">Whole (precision={1})</div>\n                        <Rating precision={1} defaultValue={3} showValue />\n                    </div>\n                    <div>\n                        <div className=\"text-sm mb-2 opacity-70\">Half ({halfValue})</div>\n                        <Rating precision={0.5} value={halfValue} onChange={setHalfValue} showValue />\n                    </div>\n                    <div>\n                        <div className=\"text-sm mb-2 opacity-70\">Decimal ({decValue.toFixed(1)})</div>\n                        <Rating precision={0.1} value={decValue} onChange={setDecValue} showValue />\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default Precision;\n"
        },
        {
          "title": "Shapes",
          "code": "import React from 'react';\nimport { Rating, RatingShape } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst shapes: { shape: RatingShape; label: string; variant: 'warning' | 'danger' | 'primary' | 'success' | 'info' }[] = [\n    { shape: 'star', label: 'Stars', variant: 'warning' },\n    { shape: 'heart', label: 'Hearts', variant: 'danger' },\n    { shape: 'thumb', label: 'Thumbs', variant: 'primary' },\n    { shape: 'circle', label: 'Circles', variant: 'info' },\n    { shape: 'square', label: 'Squares', variant: 'success' },\n];\n\nconst code = `<Rating shape=\"star\" defaultValue={3} />\n<Rating shape=\"heart\" variant=\"danger\" defaultValue={3} />\n<Rating shape=\"thumb\" variant=\"primary\" defaultValue={3} />\n<Rating shape=\"circle\" variant=\"info\" defaultValue={3} />\n<Rating shape=\"square\" variant=\"success\" defaultValue={3} />`;\n\nconst Shapes: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Shapes\" description=\"Five built-in shapes: star, heart, thumb, circle, and square.\">\n            <div className=\"space-y-4\">\n                {shapes.map(({ shape, label, variant }) => (\n                    <div key={shape} className=\"flex items-center gap-4\">\n                        <span className=\"text-xs opacity-60 w-16\">{label}</span>\n                        <Rating shape={shape} variant={variant} defaultValue={3} />\n                    </div>\n                ))}\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default Shapes;\n"
        },
        {
          "title": "Sizes",
          "code": "import React from 'react';\nimport { Rating, RatingSize } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst sizes: RatingSize[] = ['xs', 'sm', 'md', 'lg', 'xl'];\n\nconst code = `<Rating defaultValue={3} size=\"xs\" />\n<Rating defaultValue={3} size=\"sm\" />\n<Rating defaultValue={3} size=\"md\" />\n<Rating defaultValue={3} size=\"lg\" />\n<Rating defaultValue={3} size=\"xl\" />`;\n\nconst Sizes: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Sizes\" description=\"Five sizes from xs to xl with proportional icon scaling.\">\n            <div className=\"space-y-4\">\n                {sizes.map((s) => (\n                    <div key={s} className=\"flex items-center gap-4\">\n                        <span className=\"text-xs opacity-60 w-8\">{s}</span>\n                        <Rating defaultValue={3} size={s} />\n                    </div>\n                ))}\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default Sizes;\n"
        },
        {
          "title": "Variants",
          "code": "import React from 'react';\nimport { Rating, RatingVariant } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst variants: RatingVariant[] = ['default', 'primary', 'success', 'warning', 'danger', 'info'];\n\nconst code = `<Rating variant=\"warning\" defaultValue={4} />\n<Rating variant=\"primary\" defaultValue={4} />\n<Rating variant=\"success\" defaultValue={4} />\n<Rating variant=\"danger\" defaultValue={4} />\n<Rating variant=\"info\" defaultValue={4} />`;\n\nconst Variants: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Color Variants\" description=\"Six semantic color variants using theme CSS variables.\">\n            <div className=\"space-y-3\">\n                {variants.map((v) => (\n                    <div key={v} className=\"flex items-center gap-4\">\n                        <span className=\"text-xs opacity-60 w-16\">{v}</span>\n                        <Rating variant={v} defaultValue={4} />\n                    </div>\n                ))}\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default Variants;\n"
        }
      ],
      "props": {
        "ratingProps": {
          "value": {
            "type": "number",
            "description": "Controlled value of the rating."
          },
          "defaultValue": {
            "type": "number",
            "default": "0",
            "description": "Initial value for uncontrolled usage."
          },
          "count": {
            "type": "number",
            "default": "5",
            "description": "Total number of rating items."
          },
          "size": {
            "type": "'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'xxl'",
            "default": "'md'",
            "description": "Icon size. Use 'xxl' (~48px) on touch surfaces to clear the 44x44 touch-target requirement."
          },
          "variant": {
            "type": "'default' | 'primary' | 'success' | 'warning' | 'danger' | 'info'",
            "default": "'warning'",
            "description": "Color variant."
          },
          "shape": {
            "type": "'star' | 'heart' | 'circle' | 'square' | 'thumb'",
            "default": "'star'",
            "description": "Built-in icon shape."
          },
          "precision": {
            "type": "1 | 0.5 | 0.1",
            "default": "1",
            "description": "Increment precision. Use 0.5 for half-star and 0.1 for decimal ratings."
          },
          "readOnly": {
            "type": "boolean",
            "default": "false",
            "description": "Display-only mode."
          },
          "disabled": {
            "type": "boolean",
            "default": "false",
            "description": "Disable interaction."
          },
          "allowClear": {
            "type": "boolean",
            "default": "true",
            "description": "Clicking the current value clears it (precision=1 only)."
          },
          "showValue": {
            "type": "boolean",
            "default": "false",
            "description": "Display the current value next to the rating."
          },
          "valueFormat": {
            "type": "(value, max) => ReactNode",
            "description": "Custom formatter for the displayed value."
          },
          "tooltips": {
            "type": "string[]",
            "description": "Per-star tooltip text shown on hover."
          },
          "labels": {
            "type": "string[]",
            "description": "Labels shown next to the rating, changing with hover/selection."
          },
          "icon": {
            "type": "ReactNode",
            "description": "Override the filled icon."
          },
          "emptyIcon": {
            "type": "ReactNode",
            "description": "Override the empty icon."
          },
          "onChange": {
            "type": "(value: number) => void",
            "description": "Called when the user selects a new value."
          },
          "onHoverChange": {
            "type": "(value: number) => void",
            "description": "Called when the hovered value changes."
          }
        }
      },
      "storyDir": "rating"
    },
    "ReportBuilder": {
      "name": "ReportBuilder",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {
        "builderProps": {
          "definition": {
            "type": "ReportDefinition",
            "description": "Initial or controlled report definition JSON."
          },
          "onChange": {
            "type": "(def: ReportDefinition) => void",
            "description": "Fires on every definition change."
          },
          "datasourcePlugins": {
            "type": "DatasourcePlugin[]",
            "description": "Registered datasource type plugins."
          },
          "parameterPlugins": {
            "type": "CustomParameterPlugin[]",
            "description": "Optional custom parameter type plugins."
          },
          "availableSubReports": {
            "type": "AvailableSubReport[]",
            "description": "Sub-reports the designer can reference. Include parameters array for auto-discovery."
          },
          "layoutState": {
            "type": "DockedLayoutState",
            "description": "Controlled panel layout state for persistence."
          },
          "onLayoutChange": {
            "type": "(state: DockedLayoutState) => void",
            "description": "Fires on panel layout change."
          },
          "panelConfig": {
            "type": "Record<string, { userCanMove?, userCanClose? }>",
            "description": "Per-panel move/close overrides (toolbox, datasource, properties, styles, console, parameters)."
          },
          "breakpoints": {
            "type": "ReportBreakpoint[]",
            "description": "Responsive breakpoints for panel layout."
          },
          "templates": {
            "type": "ReportTemplate[]",
            "description": "Available report templates."
          },
          "onSaveTemplate": {
            "type": "(template: ReportTemplate) => void",
            "description": "Called when user saves a template."
          },
          "onDeleteTemplate": {
            "type": "(templateId: string) => void",
            "description": "Called when user deletes a template."
          },
          "onLoadTemplate": {
            "type": "(template: ReportTemplate) => void",
            "description": "Called when user loads a template."
          },
          "enableMultiTab": {
            "type": "boolean",
            "default": false,
            "description": "Enable multi-tab editing mode."
          },
          "tabs": {
            "type": "ReportTab[]",
            "description": "Array of tabs when multi-tab is enabled."
          },
          "activeTabId": {
            "type": "string",
            "description": "Currently active tab ID."
          },
          "onTabChange": {
            "type": "(tabId: string) => void",
            "description": "Called when active tab changes."
          },
          "onTabClose": {
            "type": "(tabId: string) => void",
            "description": "Called when a tab is closed."
          },
          "className": {
            "type": "string",
            "description": "Additional CSS class."
          },
          "style": {
            "type": "CSSProperties",
            "description": "Inline styles."
          }
        },
        "viewerProps": {
          "definition": {
            "type": "ReportDefinition",
            "required": true,
            "description": "The report definition JSON to render."
          },
          "datasourcePlugins": {
            "type": "DatasourcePlugin[]",
            "required": true,
            "description": "Plugins used to fetch datasource data."
          },
          "parameterValues": {
            "type": "Record<string, unknown>",
            "description": "Controlled parameter values."
          },
          "onParameterChange": {
            "type": "(values: Record<string, unknown>) => void",
            "description": "Fires when end-user changes parameter values."
          },
          "parameterPanel": {
            "type": "{ mode: \"popover\" | \"docked\"; position?: \"left\" | \"right\" | \"top\" }",
            "description": "Parameter panel display mode and position."
          },
          "subReportDefinitions": {
            "type": "SubReportDefinition[]",
            "description": "Available sub-report definitions for recursive rendering."
          },
          "onColumnResize": {
            "type": "(componentId, columnId, width) => void",
            "description": "Fires when user resizes a table column."
          },
          "onColumnReorder": {
            "type": "(componentId, columnIds) => void",
            "description": "Fires when user reorders table columns via drag."
          },
          "onDrillThrough": {
            "type": "(parameterName, value) => void",
            "description": "Fires when user clicks a table row or chart element for drill-through."
          },
          "onCellEdit": {
            "type": "(componentId, rowIndex, field, value) => void",
            "description": "Fires when user edits a table cell (double-click to edit)."
          },
          "syncParamsToHash": {
            "type": "boolean",
            "default": false,
            "description": "Sync parameter values to URL hash for bookmarkable state."
          },
          "hideToolbar": {
            "type": "boolean",
            "default": false,
            "description": "Hide the built-in toolbar. Use with viewerRef to provide your own controls."
          },
          "viewerRef": {
            "type": "React.Ref<ReportViewerHandle>",
            "description": "Ref to access viewer actions (exportPdf, print, refresh) from external buttons."
          },
          "className": {
            "type": "string",
            "description": "Additional CSS class."
          },
          "style": {
            "type": "CSSProperties",
            "description": "Inline styles."
          }
        }
      }
    },
    "Resizable": {
      "name": "Resizable",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "AspectRatioGrid",
          "code": "import React from 'react';\nimport { Resizable } from '../../../components/resizable';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<Resizable aspectRatio={16 / 9} defaultWidth={320} defaultHeight={180}>...</Resizable>\n<Resizable grid={[20, 20]} defaultWidth={320} defaultHeight={200}>...</Resizable>`;\n\nconst cardStyle: React.CSSProperties = {\n    width: '100%',\n    height: '100%',\n    background: 'linear-gradient(135deg, var(--eui-primary-subtle), var(--eui-bg-subtle))',\n    border: '1px solid var(--eui-border)',\n    borderRadius: 8,\n    display: 'flex',\n    alignItems: 'center',\n    justifyContent: 'center',\n    color: 'var(--eui-text)',\n    fontSize: 13,\n    fontWeight: 500,\n};\n\nconst AspectRatioGrid: React.FC = () => (\n    <ComponentDemo\n        title=\"Aspect Ratio & Grid Snap\"\n        description=\"Lock to an aspect ratio while resizing, or snap to a pixel grid.\"\n    >\n        <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16 }}>\n            <div style={{ display: 'flex', flexWrap: 'wrap', gap: 16, justifyContent: 'center' }}>\n                <Resizable aspectRatio={16 / 9} defaultWidth={320} defaultHeight={180} ariaLabel=\"16:9 ratio\">\n                    <div style={cardStyle}>16:9 aspect</div>\n                </Resizable>\n                <Resizable aspectRatio={1} defaultWidth={200} defaultHeight={200} ariaLabel=\"Square ratio\">\n                    <div style={cardStyle}>1:1 square</div>\n                </Resizable>\n                <Resizable grid={[20, 20]} defaultWidth={320} defaultHeight={200} ariaLabel=\"Snaps to grid\">\n                    <div style={cardStyle}>grid: 20×20</div>\n                </Resizable>\n            </div>\n            <CodeBlock code={code} />\n        </div>\n    </ComponentDemo>\n);\n\nexport default AspectRatioGrid;\n"
        },
        {
          "title": "AxisAndHandles",
          "code": "import React from 'react';\nimport { Resizable } from '../../../components/resizable';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<Resizable axis=\"horizontal\" defaultWidth={280} defaultHeight={140}>...</Resizable>\n<Resizable axis=\"vertical\" defaultWidth={240} defaultHeight={160}>...</Resizable>\n<Resizable handles=\"corners\" defaultWidth={240} defaultHeight={160}>...</Resizable>`;\n\nconst cardStyle: React.CSSProperties = {\n    width: '100%',\n    height: '100%',\n    background: 'var(--eui-bg-subtle)',\n    border: '1px solid var(--eui-border)',\n    borderRadius: 8,\n    display: 'flex',\n    alignItems: 'center',\n    justifyContent: 'center',\n    color: 'var(--eui-text-muted)',\n    fontSize: 13,\n};\n\nconst AxisAndHandles: React.FC = () => (\n    <ComponentDemo\n        title=\"Axis & Handle Sets\"\n        description=\"Restrict resize to one axis or render only a subset of handles.\"\n    >\n        <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16 }}>\n            <div style={{ display: 'flex', flexWrap: 'wrap', gap: 16, justifyContent: 'center' }}>\n                <Resizable axis=\"horizontal\" defaultWidth={280} defaultHeight={140} ariaLabel=\"Horizontal only\">\n                    <div style={cardStyle}>axis: horizontal</div>\n                </Resizable>\n                <Resizable axis=\"vertical\" defaultWidth={240} defaultHeight={160} ariaLabel=\"Vertical only\">\n                    <div style={cardStyle}>axis: vertical</div>\n                </Resizable>\n                <Resizable handles=\"corners\" defaultWidth={240} defaultHeight={160} ariaLabel=\"Corners only\">\n                    <div style={cardStyle}>handles: corners</div>\n                </Resizable>\n                <Resizable handles=\"edges\" defaultWidth={240} defaultHeight={160} ariaLabel=\"Edges only\">\n                    <div style={cardStyle}>handles: edges</div>\n                </Resizable>\n            </div>\n            <CodeBlock code={code} />\n        </div>\n    </ComponentDemo>\n);\n\nexport default AxisAndHandles;\n"
        },
        {
          "title": "BasicUsage",
          "code": "import React, { useState } from 'react';\nimport { Resizable } from '../../../components/resizable';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { Resizable } from 'fluxo-ui';\n\n<Resizable defaultWidth={320} defaultHeight={200} minWidth={120} minHeight={80}>\n  <div className=\"p-4\">\n    Resize me using any of the 8 handles.\n  </div>\n</Resizable>`;\n\nconst BasicUsage: React.FC = () => {\n    const [size, setSize] = useState({ width: 320, height: 200 });\n\n    return (\n        <ComponentDemo\n            title=\"Basic Resize\"\n            description=\"Grab any of the 8 handles (4 corners, 4 edges) to resize. Keyboard arrows work too — focus a handle with Tab.\"\n        >\n            <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16 }}>\n                <div style={{ display: 'flex', justifyContent: 'center', padding: 16 }}>\n                    <Resizable\n                        defaultWidth={320}\n                        defaultHeight={200}\n                        minWidth={120}\n                        minHeight={80}\n                        ariaLabel=\"Demo card\"\n                        onSizeChange={setSize}\n                    >\n                        <div\n                            style={{\n                                width: '100%',\n                                height: '100%',\n                                background: 'var(--eui-bg-subtle)',\n                                border: '1px solid var(--eui-border)',\n                                borderRadius: 8,\n                                display: 'flex',\n                                alignItems: 'center',\n                                justifyContent: 'center',\n                                color: 'var(--eui-text)',\n                                fontSize: 14,\n                                fontWeight: 500,\n                            }}\n                        >\n                            Drag any edge or corner\n                        </div>\n                    </Resizable>\n                </div>\n                <div\n                    style={{\n                        padding: '10px 14px',\n                        background: 'var(--eui-bg-subtle)',\n                        border: '1px solid var(--eui-border-subtle)',\n                        borderRadius: 6,\n                        fontSize: 12,\n                        color: 'var(--eui-text-muted)',\n                    }}\n                >\n                    Current size: <strong style={{ color: 'var(--eui-text)' }}>{Math.round(size.width)} × {Math.round(size.height)} px</strong>\n                </div>\n                <CodeBlock code={code} />\n            </div>\n        </ComponentDemo>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "Controlled",
          "code": "import React, { useState } from 'react';\nimport { Resizable } from '../../../components/resizable';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `const [size, setSize] = useState({ width: 320, height: 200 });\n\n<Resizable\n  width={size.width}\n  height={size.height}\n  onSizeChange={setSize}\n  minWidth={120}\n  minHeight={80}\n>\n  ...\n</Resizable>\n<input type=\"range\" min={120} max={500} value={size.width}\n  onChange={(e) => setSize(s => ({ ...s, width: +e.target.value }))} />`;\n\nconst Controlled: React.FC = () => {\n    const [size, setSize] = useState({ width: 320, height: 200 });\n\n    return (\n        <ComponentDemo\n            title=\"Controlled Mode\"\n            description=\"Provide width and height props (and listen to onSizeChange) for two-way binding with external controls.\"\n        >\n            <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16 }}>\n                <div style={{ display: 'flex', justifyContent: 'center', padding: 16 }}>\n                    <Resizable\n                        width={size.width}\n                        height={size.height}\n                        minWidth={120}\n                        minHeight={80}\n                        maxWidth={520}\n                        maxHeight={400}\n                        onSizeChange={setSize}\n                        ariaLabel=\"Controlled card\"\n                    >\n                        <div\n                            style={{\n                                width: '100%',\n                                height: '100%',\n                                background: 'var(--eui-bg-subtle)',\n                                border: '1px solid var(--eui-border)',\n                                borderRadius: 8,\n                                display: 'flex',\n                                alignItems: 'center',\n                                justifyContent: 'center',\n                                color: 'var(--eui-text)',\n                                fontSize: 13,\n                            }}\n                        >\n                            Drive me from the sliders below\n                        </div>\n                    </Resizable>\n                </div>\n                <div\n                    style={{\n                        padding: 14,\n                        background: 'var(--eui-bg-subtle)',\n                        border: '1px solid var(--eui-border-subtle)',\n                        borderRadius: 6,\n                        display: 'flex',\n                        flexDirection: 'column',\n                        gap: 12,\n                    }}\n                >\n                    <label style={{ display: 'flex', alignItems: 'center', gap: 12, fontSize: 13, color: 'var(--eui-text)' }}>\n                        <span style={{ width: 60 }}>Width</span>\n                        <input\n                            type=\"range\"\n                            min={120}\n                            max={520}\n                            value={size.width}\n                            onChange={(e) => setSize((s) => ({ ...s, width: +e.target.value }))}\n                            style={{ flex: 1 }}\n                            aria-label=\"Width\"\n                        />\n                        <span style={{ width: 60, textAlign: 'right' }}>{Math.round(size.width)} px</span>\n                    </label>\n                    <label style={{ display: 'flex', alignItems: 'center', gap: 12, fontSize: 13, color: 'var(--eui-text)' }}>\n                        <span style={{ width: 60 }}>Height</span>\n                        <input\n                            type=\"range\"\n                            min={80}\n                            max={400}\n                            value={size.height}\n                            onChange={(e) => setSize((s) => ({ ...s, height: +e.target.value }))}\n                            style={{ flex: 1 }}\n                            aria-label=\"Height\"\n                        />\n                        <span style={{ width: 60, textAlign: 'right' }}>{Math.round(size.height)} px</span>\n                    </label>\n                </div>\n                <CodeBlock code={code} />\n            </div>\n        </ComponentDemo>\n    );\n};\n\nexport default Controlled;\n"
        },
        {
          "title": "ImageResizer",
          "code": "import React from 'react';\nimport { Resizable } from '../../../components/resizable';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<Resizable\n  defaultWidth={300}\n  defaultHeight={200}\n  minWidth={120}\n  minHeight={80}\n  showHandles=\"hover\"\n  ariaLabel=\"Photo\"\n>\n  <img src=\"/photo.jpg\" alt=\"Mountain view\" style={{ width: '100%', height: '100%', objectFit: 'cover', borderRadius: 8 }} />\n</Resizable>`;\n\nconst ImageResizer: React.FC = () => (\n    <ComponentDemo\n        title=\"Resizable Media\"\n        description=\"Wrap any element — including images, iframes, or charts. Handles only appear on hover with showHandles='hover'.\"\n    >\n        <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16 }}>\n            <div style={{ display: 'flex', justifyContent: 'center', padding: 16 }}>\n                <Resizable\n                    defaultWidth={320}\n                    defaultHeight={200}\n                    minWidth={120}\n                    minHeight={80}\n                    aspectRatio\n                    showHandles=\"hover\"\n                    ariaLabel=\"Photo\"\n                >\n                    <div\n                        style={{\n                            width: '100%',\n                            height: '100%',\n                            borderRadius: 8,\n                            background: 'linear-gradient(120deg, #60a5fa, #a78bfa, #f472b6)',\n                            display: 'flex',\n                            alignItems: 'center',\n                            justifyContent: 'center',\n                            color: '#fff',\n                            fontWeight: 600,\n                            boxShadow: 'var(--eui-shadow)',\n                        }}\n                    >\n                        Hover to reveal handles\n                    </div>\n                </Resizable>\n            </div>\n            <CodeBlock code={code} />\n        </div>\n    </ComponentDemo>\n);\n\nexport default ImageResizer;\n"
        }
      ],
      "props": {
        "resizableProps": {
          "children": {
            "type": "React.ReactNode",
            "required": true,
            "description": "Element(s) wrapped by the resizable container."
          },
          "defaultWidth": {
            "type": "number | string",
            "description": "Initial width in pixels (uncontrolled). Strings are parsed for the leading number."
          },
          "defaultHeight": {
            "type": "number | string",
            "description": "Initial height in pixels (uncontrolled)."
          },
          "width": {
            "type": "number",
            "description": "Controlled width in pixels. Provide together with `height` and listen to `onSizeChange`."
          },
          "height": {
            "type": "number",
            "description": "Controlled height in pixels. Provide together with `width` and listen to `onSizeChange`."
          },
          "onSizeChange": {
            "type": "(size: { width: number; height: number }) => void",
            "description": "Fires on every committed size change (mouse, touch, keyboard)."
          },
          "onResizeStart": {
            "type": "(event: ResizeStartEvent) => void",
            "description": "Fires when the user grabs a handle."
          },
          "onResize": {
            "type": "(event: ResizeChangeEvent) => void",
            "description": "Fires continuously while resizing."
          },
          "onResizeEnd": {
            "type": "(event: ResizeEndEvent) => void",
            "description": "Fires when the user releases the handle."
          },
          "axis": {
            "type": "'horizontal' | 'vertical' | 'both'",
            "default": "'both'",
            "description": "Restrict resize direction. Handles incompatible with the axis are hidden."
          },
          "handles": {
            "type": "ResizeHandlePosition[] | 'all' | 'corners' | 'edges'",
            "default": "'all'",
            "description": "Which handles to render. `'corners'` = `['ne','nw','se','sw']`, `'edges'` = `['n','s','e','w']`."
          },
          "minWidth": {
            "type": "number",
            "default": "40",
            "description": "Minimum width in pixels."
          },
          "minHeight": {
            "type": "number",
            "default": "40",
            "description": "Minimum height in pixels."
          },
          "maxWidth": {
            "type": "number",
            "default": "Infinity",
            "description": "Maximum width in pixels."
          },
          "maxHeight": {
            "type": "number",
            "default": "Infinity",
            "description": "Maximum height in pixels."
          },
          "grid": {
            "type": "[number, number]",
            "description": "Snap size to a [widthStep, heightStep] grid."
          },
          "aspectRatio": {
            "type": "number | boolean",
            "description": "Lock to a specific aspect ratio (number) or to the starting ratio (true)."
          },
          "lockAspectRatio": {
            "type": "boolean",
            "default": "false",
            "description": "Convenience alias for `aspectRatio = true`."
          },
          "disabled": {
            "type": "boolean",
            "default": "false",
            "description": "Disable all resize interaction; handles are hidden."
          },
          "handleSize": {
            "type": "number",
            "default": "8",
            "description": "Visual / hit area thickness of each handle in pixels."
          },
          "showHandles": {
            "type": "'always' | 'hover' | 'never'",
            "default": "'always'",
            "description": "When handles are visible. `'hover'` reveals them on container hover or focus."
          },
          "keyboardStep": {
            "type": "number",
            "default": "8",
            "description": "Pixels per arrow-key press on a focused handle."
          },
          "keyboardBigStep": {
            "type": "number",
            "default": "32",
            "description": "Pixels per Shift+arrow press on a focused handle."
          },
          "bounds": {
            "type": "'parent' | 'window' | { width: number; height: number }",
            "description": "Optional upper bound for size. Useful inside scroll containers."
          },
          "className": {
            "type": "string",
            "description": "Class name applied to the container."
          },
          "style": {
            "type": "React.CSSProperties",
            "description": "Inline styles for the container (merged with computed width/height)."
          },
          "handleClassName": {
            "type": "string",
            "description": "Class name applied to every resize handle."
          },
          "ariaLabel": {
            "type": "string",
            "description": "Used as the prefix for each handle's aria-label, e.g. \"Widget resize se\"."
          }
        }
      },
      "storyDir": "resizable"
    },
    "SafeAreaView": {
      "name": "SafeAreaView",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React from 'react';\nimport { SafeAreaView } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { SafeAreaView } from 'fluxo-ui';\n\n<SafeAreaView edges={['top', 'bottom']} fillBackground>\n    {/* page content */}\n</SafeAreaView>`;\n\nconst phoneFrame: React.CSSProperties = {\n    width: 320,\n    height: 220,\n    border: '1px solid var(--eui-border-subtle)',\n    borderRadius: 16,\n    overflow: 'hidden',\n    background: '#000',\n    position: 'relative',\n    boxShadow: '0 8px 24px rgba(0, 0, 0, 0.15)',\n};\n\nconst notch: React.CSSProperties = {\n    position: 'absolute',\n    top: 0,\n    left: '50%',\n    transform: 'translateX(-50%)',\n    width: 80,\n    height: 18,\n    background: '#000',\n    borderBottomLeftRadius: 12,\n    borderBottomRightRadius: 12,\n    zIndex: 2,\n};\n\nconst homeBar: React.CSSProperties = {\n    position: 'absolute',\n    bottom: 6,\n    left: '50%',\n    transform: 'translateX(-50%)',\n    width: 96,\n    height: 4,\n    background: '#fff',\n    borderRadius: 999,\n    opacity: 0.6,\n    zIndex: 2,\n};\n\nconst BasicUsage: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Respecting the notch and home indicator\" description=\"SafeAreaView applies env(safe-area-inset-*) padding so your UI clears iOS notches and home bars. The mock device on the right shows the simulated effect using inline insets.\">\n            <div style={{ display: 'flex', gap: 24, flexWrap: 'wrap', alignItems: 'flex-start', justifyContent: 'center' }}>\n                <div style={phoneFrame}>\n                    <div style={notch} />\n                    <SafeAreaView\n                        edges={['top', 'bottom']}\n                        fillBackground\n                        style={{ height: '100%', boxSizing: 'border-box', display: 'flex', flexDirection: 'column', justifyContent: 'space-between', ['--eui-safe-top' as never]: '22px', ['--eui-safe-bottom' as never]: '18px' }}\n                    >\n                        <div style={{ padding: '8px 16px', color: 'var(--eui-text)', fontWeight: 600 }}>App Header</div>\n                        <div style={{ padding: '8px 16px', color: 'var(--eui-text-muted)' }}>Body content here</div>\n                        <div style={{ padding: '8px 16px', color: 'var(--eui-primary)', fontWeight: 600 }}>Bottom action</div>\n                    </SafeAreaView>\n                    <div style={homeBar} />\n                </div>\n                <div style={{ flex: 1, minWidth: 220, color: 'var(--eui-text-muted)', fontSize: 13 }}>\n                    The SafeAreaView wrapper applies the iOS safe-area insets as padding (or margin). On a real device, no JS or CSS variable override is needed — env(safe-area-inset-top) / -bottom are picked up automatically.\n                </div>\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\"><CodeBlock code={code} language=\"tsx\" /></div>\n    </>\n);\n\nexport default BasicUsage;\n"
        },
        {
          "title": "EdgesAndModes",
          "code": "import React from 'react';\nimport { SafeAreaView } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<SafeAreaView edges=\"top\" mode=\"padding\">Header area</SafeAreaView>\n<SafeAreaView edges={['bottom', 'horizontal']} mode=\"margin\">…</SafeAreaView>\n<SafeAreaView edges=\"all\" as=\"main\" fillBackground>…</SafeAreaView>`;\n\nconst cellBase: React.CSSProperties = {\n    border: '1px solid var(--eui-border-subtle)',\n    borderRadius: 8,\n    padding: 12,\n    color: 'var(--eui-text)',\n    background: 'var(--eui-bg)',\n};\n\nconst EdgesAndModes: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Targeted edges\" description=\"Pass any combination of 'top' | 'right' | 'bottom' | 'left' | 'horizontal' | 'vertical' | 'all'. The wrapper applies env(safe-area-inset-*) only to the chosen edges.\">\n            <div style={{ display: 'flex', flexDirection: 'column', gap: 12, width: '100%', maxWidth: 420 }}>\n                <SafeAreaView edges=\"top\" style={{ ...cellBase, ['--eui-safe-top' as never]: '24px' }}>\n                    edges=&quot;top&quot;\n                </SafeAreaView>\n                <SafeAreaView edges={['bottom', 'horizontal']} style={{ ...cellBase, ['--eui-safe-bottom' as never]: '20px', ['--eui-safe-left' as never]: '16px', ['--eui-safe-right' as never]: '16px' }}>\n                    edges={`{['bottom', 'horizontal']}`}\n                </SafeAreaView>\n                <SafeAreaView edges=\"all\" style={{ ...cellBase, ['--eui-safe-top' as never]: '14px', ['--eui-safe-right' as never]: '14px', ['--eui-safe-bottom' as never]: '14px', ['--eui-safe-left' as never]: '14px' }}>\n                    edges=&quot;all&quot;\n                </SafeAreaView>\n            </div>\n        </ComponentDemo>\n\n        <ComponentDemo title=\"Padding vs margin\" description=\"Use mode='margin' when you want the wrapper itself to sit inside the safe area without nudging its inner padding.\" className=\"mt-4\">\n            <div style={{ display: 'flex', flexDirection: 'column', gap: 12, width: '100%', maxWidth: 420 }}>\n                <SafeAreaView edges=\"vertical\" mode=\"padding\" style={{ ...cellBase, ['--eui-safe-top' as never]: '14px', ['--eui-safe-bottom' as never]: '14px' }}>\n                    mode=&quot;padding&quot; — content sits inside the safe area.\n                </SafeAreaView>\n                <SafeAreaView edges=\"vertical\" mode=\"margin\" style={{ ...cellBase, ['--eui-safe-top' as never]: '14px', ['--eui-safe-bottom' as never]: '14px' }}>\n                    mode=&quot;margin&quot; — the wrapper itself is pushed inward.\n                </SafeAreaView>\n            </div>\n        </ComponentDemo>\n\n        <div className=\"mt-4\"><CodeBlock code={code} language=\"tsx\" /></div>\n    </>\n);\n\nexport default EdgesAndModes;\n"
        }
      ],
      "props": {
        "safeAreaViewProps": {
          "edges": {
            "type": "SafeAreaEdge | SafeAreaEdge[]",
            "default": "'all'",
            "description": "Which insets to apply. Supports 'top' | 'right' | 'bottom' | 'left' | 'all' | 'horizontal' | 'vertical', or an array of those."
          },
          "mode": {
            "type": "'padding' | 'margin'",
            "default": "'padding'",
            "description": "Apply the insets as padding (default) or margin."
          },
          "as": {
            "type": "keyof JSX.IntrinsicElements",
            "default": "'div'",
            "description": "HTML element to render as (e.g., 'main', 'section', 'header', 'footer')."
          },
          "fillBackground": {
            "type": "boolean",
            "default": "false",
            "description": "Apply the theme background to the wrapper so notch areas look consistent."
          },
          "children": {
            "type": "ReactNode",
            "description": "Content rendered inside the safe area wrapper."
          },
          "className": {
            "type": "string",
            "description": "Additional CSS class for the wrapper."
          }
        }
      },
      "storyDir": "safe-area-view"
    },
    "ScrollToTop": {
      "name": "ScrollToTop",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React, { useEffect, useRef, useState } from 'react';\nimport { ScrollToTop } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { ScrollToTop } from 'fluxo-ui';\n\n// Mounted at the app root; auto-shows after 200px of scroll\n<ScrollToTop showAfter={200} />`;\n\nconst filler = Array.from({ length: 30 });\n\nconst BasicUsage: React.FC = () => {\n    const containerRef = useRef<HTMLDivElement | null>(null);\n    const [container, setContainer] = useState<HTMLElement | null>(null);\n\n    useEffect(() => {\n        setContainer(containerRef.current);\n    }, []);\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Default Scroll-To-Top\"\n                description=\"The button is mounted once at the app root and watches the page scroll. Below is a self-contained scroll demo — scroll inside the panel and the embedded button appears in the bottom-right corner.\"\n            >\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 12 }}>\n                    <div\n                        ref={containerRef}\n                        style={{\n                            position: 'relative',\n                            width: '100%',\n                            height: 320,\n                            overflowY: 'auto',\n                            background: 'var(--eui-bg-subtle)',\n                            border: '1px solid var(--eui-border-subtle)',\n                            borderRadius: 8,\n                            padding: 16,\n                        }}\n                    >\n                        <h4 style={{ marginTop: 0, color: 'var(--eui-text)' }}>Scroll me</h4>\n                        {filler.map((_, idx) => (\n                            <p key={idx} style={{ color: 'var(--eui-text-muted)', lineHeight: 1.6 }}>\n                                Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco.\n                            </p>\n                        ))}\n                        {container && (\n                            <div\n                                style={{\n                                    position: 'sticky',\n                                    bottom: 12,\n                                    display: 'flex',\n                                    justifyContent: 'flex-end',\n                                    pointerEvents: 'none',\n                                }}\n                            >\n                                <div style={{ pointerEvents: 'auto' }}>\n                                    <ScrollToTop target={container} mode=\"inline\" showAfter={120} size=\"md\" />\n                                </div>\n                            </div>\n                        )}\n                    </div>\n                    <div\n                        style={{\n                            padding: '10px 14px',\n                            background: 'var(--eui-bg-subtle)',\n                            border: '1px solid var(--eui-border-subtle)',\n                            borderRadius: 6,\n                            fontSize: 12,\n                            color: 'var(--eui-text-muted)',\n                        }}\n                    >\n                        In production, drop a single <code>&lt;ScrollToTop /&gt;</code> at your app root. It tracks{' '}\n                        <code>window</code> by default and floats over the viewport.\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "Sizes",
          "code": "import React from 'react';\nimport { ScrollToTop, ScrollToTopSize } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst sizes: ScrollToTopSize[] = ['sm', 'md', 'lg', 'xl'];\n\nconst code = `<ScrollToTop size=\"sm\" />\n<ScrollToTop size=\"md\" />\n<ScrollToTop size=\"lg\" />\n<ScrollToTop size=\"xl\" />\n<ScrollToTop size=\"md\" label=\"Top\" />\n<ScrollToTop size=\"md\" showProgress />`;\n\nconst Sizes: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Sizes & Optional Label\" description=\"Four sizes plus an optional text label that turns the FAB into a pill.\">\n            <div style={{ display: 'flex', gap: 16, flexWrap: 'wrap', alignItems: 'center', justifyContent: 'center' }}>\n                {sizes.map((s) => (\n                    <div key={s} style={{ display: 'flex', flexDirection: 'column', gap: 4, alignItems: 'center' }}>\n                        <ScrollToTop size={s} mode=\"inline\" showAfter={0} className=\"eui-scroll-to-top-visible\" />\n                        <span style={{ fontSize: 11, color: 'var(--eui-text-muted)' }}>{s}</span>\n                    </div>\n                ))}\n                <div style={{ display: 'flex', flexDirection: 'column', gap: 4, alignItems: 'center' }}>\n                    <ScrollToTop size=\"md\" mode=\"inline\" showAfter={0} label=\"Back to top\" className=\"eui-scroll-to-top-visible\" />\n                    <span style={{ fontSize: 11, color: 'var(--eui-text-muted)' }}>label</span>\n                </div>\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default Sizes;\n"
        },
        {
          "title": "Variants",
          "code": "import React from 'react';\nimport { ScrollToTop, ScrollToTopLayout, ScrollToTopVariant } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<ScrollToTop variant=\"primary\" />\n<ScrollToTop variant=\"success\" layout=\"outlined\" />\n<ScrollToTop layout=\"glass\" />\n<ScrollToTop gradient={{ from: '#3b82f6', to: '#a855f7' }} />`;\n\nconst variants: ScrollToTopVariant[] = ['default', 'primary', 'secondary', 'success', 'warning', 'danger', 'info'];\nconst layouts: ScrollToTopLayout[] = ['solid', 'outlined', 'glass'];\n\nconst Variants: React.FC = () => (\n    <>\n        <ComponentDemo\n            title=\"Variants × Layouts\"\n            description=\"The component is shown here in 'inline' mode so the visual treatments are easy to compare. In production, mode='fixed' (default) anchors it to a viewport corner.\"\n        >\n            <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 24 }}>\n                {layouts.map((layout) => (\n                    <div key={layout} style={{ display: 'flex', flexDirection: 'column', gap: 8, alignItems: 'center' }}>\n                        <span style={{ fontSize: 12, color: 'var(--eui-text-muted)' }}>layout=\"{layout}\"</span>\n                        <div style={{ display: 'flex', gap: 12, flexWrap: 'wrap', justifyContent: 'center' }}>\n                            {variants.map((v) => (\n                                <ScrollToTop\n                                    key={v}\n                                    variant={v}\n                                    layout={layout}\n                                    mode=\"inline\"\n                                    showAfter={0}\n                                    size=\"md\"\n                                    ariaLabel={`Scroll to top - ${v}`}\n                                    className=\"eui-scroll-to-top-visible\"\n                                />\n                            ))}\n                        </div>\n                    </div>\n                ))}\n                <div style={{ display: 'flex', flexDirection: 'column', gap: 8, alignItems: 'center' }}>\n                    <span style={{ fontSize: 12, color: 'var(--eui-text-muted)' }}>Custom color & gradient</span>\n                    <div style={{ display: 'flex', gap: 12, flexWrap: 'wrap', justifyContent: 'center' }}>\n                        <ScrollToTop mode=\"inline\" showAfter={0} color=\"#ec4899\" className=\"eui-scroll-to-top-visible\" />\n                        <ScrollToTop\n                            mode=\"inline\"\n                            showAfter={0}\n                            gradient={{ from: '#3b82f6', to: '#a855f7' }}\n                            className=\"eui-scroll-to-top-visible\"\n                        />\n                        <ScrollToTop\n                            mode=\"inline\"\n                            showAfter={0}\n                            gradient={{ from: '#22c55e', to: '#0ea5e9', angle: 60 }}\n                            label=\"Top\"\n                            className=\"eui-scroll-to-top-visible\"\n                        />\n                        <ScrollToTop\n                            mode=\"inline\"\n                            showAfter={0}\n                            color=\"#f59e0b\"\n                            layout=\"outlined\"\n                            className=\"eui-scroll-to-top-visible\"\n                        />\n                    </div>\n                </div>\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default Variants;\n"
        },
        {
          "title": "WithProgress",
          "code": "import React, { useEffect, useRef, useState } from 'react';\nimport { ScrollToTop } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<ScrollToTop showProgress size=\"lg\" gradient={{ from: '#3b82f6', to: '#a855f7' }} />`;\n\nconst filler = Array.from({ length: 40 });\n\nconst WithProgress: React.FC = () => {\n    const containerRef = useRef<HTMLDivElement | null>(null);\n    const [container, setContainer] = useState<HTMLElement | null>(null);\n    useEffect(() => {\n        setContainer(containerRef.current);\n    }, []);\n    return (\n        <>\n            <ComponentDemo\n                title=\"With Progress Ring\"\n                description=\"Set showProgress to draw a circular ring tracking how far down the user has scrolled. Pair with a gradient for a striking effect.\"\n            >\n                <div\n                    ref={containerRef}\n                    style={{\n                        position: 'relative',\n                        width: '100%',\n                        height: 360,\n                        overflowY: 'auto',\n                        background: 'var(--eui-bg-subtle)',\n                        border: '1px solid var(--eui-border-subtle)',\n                        borderRadius: 8,\n                        padding: 16,\n                    }}\n                >\n                    <h4 style={{ marginTop: 0, color: 'var(--eui-text)' }}>Scroll me</h4>\n                    {filler.map((_, idx) => (\n                        <p key={idx} style={{ color: 'var(--eui-text-muted)', lineHeight: 1.6 }}>\n                            Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n                        </p>\n                    ))}\n                    {container && (\n                        <div\n                            style={{\n                                position: 'sticky',\n                                bottom: 12,\n                                display: 'flex',\n                                justifyContent: 'flex-end',\n                                pointerEvents: 'none',\n                            }}\n                        >\n                            <div style={{ pointerEvents: 'auto' }}>\n                                <ScrollToTop\n                                    target={container}\n                                    mode=\"inline\"\n                                    showAfter={80}\n                                    showProgress\n                                    size=\"lg\"\n                                    gradient={{ from: '#3b82f6', to: '#a855f7' }}\n                                />\n                            </div>\n                        </div>\n                    )}\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default WithProgress;\n"
        }
      ],
      "props": {
        "scrollToTopProps": {
          "target": {
            "type": "HTMLElement | string",
            "description": "Scroll target element or selector (default: window)"
          },
          "showAfter": {
            "type": "number",
            "default": "200",
            "description": "Pixels of scroll required before the button appears"
          },
          "position": {
            "type": "'bottom-right' | 'bottom-left' | 'top-right' | 'top-left'",
            "default": "'bottom-right'",
            "description": "Corner the button anchors to (in 'fixed' mode)"
          },
          "offset": {
            "type": "{ x?: number; y?: number }",
            "default": "{ x: 24, y: 24 }",
            "description": "Distance from the chosen corner in px"
          },
          "size": {
            "type": "'sm' | 'md' | 'lg' | 'xl'",
            "default": "'md'",
            "description": "Preset size"
          },
          "variant": {
            "type": "'default' | 'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info'",
            "default": "'primary'",
            "description": "Color variant"
          },
          "layout": {
            "type": "'solid' | 'outlined' | 'glass'",
            "default": "'solid'",
            "description": "Visual treatment"
          },
          "color": {
            "type": "string",
            "description": "Override variant color with any CSS color"
          },
          "gradient": {
            "type": "{ from: string; to: string; angle?: number }",
            "description": "Gradient background overrides variant/color"
          },
          "icon": {
            "type": "IconComponent | ReactElement",
            "description": "Icon shown inside the button (default: chevron-up)"
          },
          "label": {
            "type": "string",
            "description": "Optional visible text next to the icon"
          },
          "showProgress": {
            "type": "boolean",
            "default": "false",
            "description": "Render a circular progress ring around the icon"
          },
          "progressColor": {
            "type": "string",
            "description": "Color of the progress ring"
          },
          "mode": {
            "type": "'fixed' | 'inline'",
            "default": "'fixed'",
            "description": "'fixed' floats over the viewport; 'inline' renders inside its parent"
          },
          "behavior": {
            "type": "'smooth' | 'auto'",
            "default": "'smooth'",
            "description": "Scroll behavior; auto-falls back under prefers-reduced-motion"
          },
          "onClick": {
            "type": "() => void",
            "description": "Fires after the scroll begins"
          },
          "id": {
            "type": "string",
            "description": "HTML id attribute"
          },
          "className": {
            "type": "string",
            "description": "Additional CSS classes"
          },
          "ariaLabel": {
            "type": "string",
            "default": "'Scroll to top'",
            "description": "Accessible label"
          }
        }
      },
      "storyDir": "scroll-to-top"
    },
    "Shimmer": {
      "name": "Shimmer",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "ProfileCard",
          "code": "import React from 'react';\nimport { ShimmerDiv } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst ProfileCard: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo title=\"Custom card layout\" description=\"Combine ShimmerDiv blocks to create any skeleton layout.\">\n                <div className=\"flex gap-4 w-full max-w-md\">\n                    <ShimmerDiv style={{ width: 56, height: 56, borderRadius: '50%' }} />\n                    <div className=\"flex-1 space-y-3 pt-1\">\n                        <ShimmerDiv style={{ height: 16, width: '50%', borderRadius: 4 }} />\n                        <ShimmerDiv style={{ height: 12, width: '80%', borderRadius: 4 }} />\n                        <ShimmerDiv style={{ height: 12, width: '65%', borderRadius: 4 }} />\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock\n                    code={`<div className=\"flex gap-4\">\n  <ShimmerDiv width={56} height={56} borderRadius=\"50%\" />\n  <div className=\"flex-1 space-y-2\">\n    <ShimmerDiv height={16} width=\"50%\" borderRadius={4} />\n    <ShimmerDiv height={12} width=\"80%\" borderRadius={4} />\n  </div>\n</div>`}\n                />\n            </div>\n        </>\n    );\n};\n\nexport default ProfileCard;\n"
        },
        {
          "title": "ShimmerBarChartDemo",
          "code": "import React from 'react';\nimport { ShimmerBarChart } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst ShimmerBarChartDemo: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo title=\"Bar chart skeleton\" description=\"Skeleton for bar chart visualizations while data loads.\">\n                <div className=\"w-full\">\n                    <ShimmerBarChart count={7} legendsCount={4} />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock\n                    code={`import { ShimmerBarChart } from 'fluxo-ui';\n\n{isLoading && <ShimmerBarChart bars={7} showXAxis showYAxis />}\n{!isLoading && <BarChart data={chartData} />}`}\n                />\n            </div>\n        </>\n    );\n};\n\nexport default ShimmerBarChartDemo;\n"
        },
        {
          "title": "ShimmerDivDemo",
          "code": "import React from 'react';\nimport { ShimmerDiv } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst ShimmerDivDemo: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo title=\"Flexible shimmer block\" description=\"The base building block for custom skeleton layouts.\">\n                <div className=\"space-y-3 w-full max-w-sm\">\n                    <ShimmerDiv style={{ height: 20, width: '60%', borderRadius: 4 }} />\n                    <ShimmerDiv style={{ height: 14, width: '90%', borderRadius: 4 }} />\n                    <ShimmerDiv style={{ height: 14, width: '75%', borderRadius: 4 }} />\n                    <ShimmerDiv style={{ height: 14, width: '80%', borderRadius: 4 }} />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock\n                    code={`import { ShimmerDiv } from 'fluxo-ui';\n\n<ShimmerDiv height={20} width=\"60%\" borderRadius={4} />\n<ShimmerDiv height={14} width=\"90%\" borderRadius={4} />\n<ShimmerDiv height={14} width=\"75%\" borderRadius={4} />`}\n                />\n            </div>\n        </>\n    );\n};\n\nexport default ShimmerDivDemo;\n"
        },
        {
          "title": "ShimmerFeedDemo",
          "code": "import React from 'react';\nimport { ShimmerFeed } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst ShimmerFeedDemo: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo\n                title=\"Feed / list skeleton\"\n                description=\"Pre-built skeleton for card feeds and list views with avatar and content lines.\"\n            >\n                <div className=\"w-full max-w-md\">\n                    <ShimmerFeed count={4} />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock\n                    code={`import { ShimmerFeed } from 'fluxo-ui';\n\n{isLoading && <ShimmerFeed />}\n{!isLoading && <FeedList items={items} />}`}\n                />\n            </div>\n        </>\n    );\n};\n\nexport default ShimmerFeedDemo;\n"
        },
        {
          "title": "ShimmerPieChartDemo",
          "code": "import React from 'react';\nimport { ShimmerPieChart } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst ShimmerPieChartDemo: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo title=\"Pie chart skeleton\" description=\"Skeleton for pie chart visualizations with optional legends.\">\n                <div className=\"w-full flex justify-center\">\n                    <ShimmerPieChart legendsCount={4} legendPosition=\"right\" />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock\n                    code={`import { ShimmerPieChart } from 'fluxo-ui';\n\n{isLoading && <ShimmerPieChart legendsCount={4} legendPosition=\"right\" />}\n{!isLoading && <PieChart data={chartData} />}`}\n                />\n            </div>\n\n            <div className=\"mt-6\">\n                <ComponentDemo title=\"Donut chart skeleton\" description=\"Donut (doughnut) variant with center hole.\">\n                    <div className=\"w-full flex justify-center\">\n                        <ShimmerPieChart doughnut legendsCount={3} legendPosition=\"bottom\" />\n                    </div>\n                </ComponentDemo>\n                <div className=\"mt-4\">\n                    <CodeBlock code={`<ShimmerPieChart doughnut legendsCount={3} legendPosition=\"bottom\" />`} />\n                </div>\n            </div>\n        </>\n    );\n};\n\nexport default ShimmerPieChartDemo;\n"
        },
        {
          "title": "ShimmerTableDemo",
          "code": "import React from 'react';\nimport { ShimmerTable } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst ShimmerTableDemo: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo title=\"Table skeleton\" description=\"Skeleton for data tables with configurable rows and columns.\">\n                <div className=\"w-full\">\n                    <ShimmerTable rows={4} columns={4} />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock\n                    code={`import { ShimmerTable } from 'fluxo-ui';\n\n{isLoading && <ShimmerTable rows={5} columns={6} showHeader />}\n{!isLoading && <DataTable rows={data} columns={columns} />}`}\n                />\n            </div>\n        </>\n    );\n};\n\nexport default ShimmerTableDemo;\n"
        }
      ],
      "props": {
        "shimmerDivProps": {
          "width": {
            "type": "string | number",
            "description": "Width of the shimmer block. Accepts CSS values (e.g. \"100%\", 200) or a number treated as pixels."
          },
          "height": {
            "type": "string | number",
            "description": "Height of the shimmer block."
          },
          "borderRadius": {
            "type": "string | number",
            "description": "Border radius of the shimmer block. Useful for circle avatars or pill shapes."
          },
          "level": {
            "type": "1 | 2 | 3 | 4 | 5 | 6",
            "default": "2",
            "description": "Background contrast level. Higher levels are darker."
          },
          "animation": {
            "type": "'shimmer' | 'pulse'",
            "default": "'shimmer'",
            "description": "Animation style: a sweeping highlight ('shimmer') or a soft fade ('pulse')."
          },
          "loadingLabel": {
            "type": "string",
            "description": "Visually-hidden text announced by screen readers (e.g., 'Loading content')."
          },
          "repeat": {
            "type": "number",
            "description": "When set, render N stacked copies (typical for list shimmers). Adds a flex-column wrapper with a configurable gap."
          },
          "gap": {
            "type": "string | number",
            "default": "'0.5rem'",
            "description": "Spacing between repeated shimmers (when `repeat` is set)."
          },
          "className": {
            "type": "string",
            "description": "Additional CSS classes applied to the root element."
          }
        },
        "skeletonLineProps": {
          "width": {
            "type": "string | number",
            "default": "'100%'",
            "description": "Width of the line. Numbers are treated as pixels."
          },
          "height": {
            "type": "string | number",
            "default": "'0.75rem'",
            "description": "Height of the line."
          },
          "radius": {
            "type": "string | number",
            "default": "'4px'",
            "description": "Corner radius of the line."
          },
          "level": {
            "type": "1 | 2 | 3 | 4 | 5 | 6",
            "default": "2",
            "description": "Background contrast level."
          },
          "animation": {
            "type": "'shimmer' | 'pulse'",
            "default": "'shimmer'",
            "description": "Animation style."
          },
          "animated": {
            "type": "boolean",
            "default": "true",
            "description": "Disable animation entirely (useful for testing or static placeholders)."
          },
          "loadingLabel": {
            "type": "string",
            "description": "Visually-hidden text announced by screen readers."
          }
        },
        "skeletonRectProps": {
          "width": {
            "type": "string | number",
            "default": "'100%'",
            "description": "Width of the rectangle."
          },
          "height": {
            "type": "string | number",
            "default": "'4rem'",
            "description": "Height of the rectangle."
          },
          "radius": {
            "type": "string | number",
            "default": "'6px'",
            "description": "Corner radius of the rectangle."
          },
          "level": {
            "type": "1 | 2 | 3 | 4 | 5 | 6",
            "default": "2",
            "description": "Background contrast level."
          },
          "animation": {
            "type": "'shimmer' | 'pulse'",
            "default": "'shimmer'",
            "description": "Animation style."
          },
          "animated": {
            "type": "boolean",
            "default": "true",
            "description": "Disable animation entirely."
          },
          "loadingLabel": {
            "type": "string",
            "description": "Visually-hidden text announced by screen readers."
          }
        },
        "shimmerTableProps": {
          "rows": {
            "type": "number",
            "default": "5",
            "description": "Number of skeleton rows to render."
          },
          "columns": {
            "type": "number",
            "default": "4",
            "description": "Number of skeleton columns to render."
          },
          "showHeader": {
            "type": "boolean",
            "default": "true",
            "description": "Whether to show the skeleton header row."
          }
        },
        "shimmerBarChartProps": {
          "bars": {
            "type": "number",
            "default": "6",
            "description": "Number of bars to display in the skeleton chart."
          },
          "showXAxis": {
            "type": "boolean",
            "default": "true",
            "description": "Whether to render placeholder labels below the bars."
          },
          "showYAxis": {
            "type": "boolean",
            "default": "true",
            "description": "Whether to render placeholder labels to the left of the chart."
          }
        },
        "skeletonListProps": {
          "rows": {
            "type": "number",
            "default": "5",
            "description": "Number of placeholder rows to render."
          },
          "variant": {
            "type": "'simple' | 'avatar-text' | 'avatar-two-line' | 'thumbnail' | 'two-line-action' | 'card-stack' | 'chat' | 'comment' | 'media'",
            "default": "'avatar-two-line'",
            "description": "Layout preset. 'simple' is a single text line per row, 'avatar-two-line' is a typical mobile list row, 'card-stack' renders content cards, 'chat' alternates left/right bubbles, 'media' renders image-on-top cards."
          },
          "showDivider": {
            "type": "boolean",
            "default": "true",
            "description": "Show a subtle separator between rows (ignored for card/media variants)."
          },
          "rowHeight": {
            "type": "string | number",
            "description": "Override the height of a row (only applies to 'simple' variant)."
          },
          "avatarSize": {
            "type": "string",
            "default": "'2.5rem'",
            "description": "Avatar/thumbnail size used by avatar variants."
          },
          "avatarShape": {
            "type": "'circle' | 'square'",
            "default": "'circle'",
            "description": "Shape used for avatar variants."
          },
          "gap": {
            "type": "string | number",
            "default": "'0.75rem'",
            "description": "Gap between rows."
          },
          "padding": {
            "type": "string | number",
            "default": "'0.75rem 1rem'",
            "description": "Outer padding of the list container."
          },
          "animated": {
            "type": "boolean",
            "default": "true",
            "description": "Toggle the shimmer animation."
          },
          "animation": {
            "type": "'shimmer' | 'pulse'",
            "default": "'shimmer'",
            "description": "Animation style."
          },
          "level": {
            "type": "1 | 2 | 3 | 4 | 5 | 6",
            "default": "2",
            "description": "Background contrast level."
          },
          "className": {
            "type": "string",
            "description": "Additional CSS class for the list root."
          },
          "loadingLabel": {
            "type": "string",
            "default": "'Loading list'",
            "description": "Visually-hidden screen reader label."
          }
        }
      },
      "storyDir": "shimmer"
    },
    "SignaturePad": {
      "name": "SignaturePad",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React, { useRef, useState } from 'react';\nimport { Button, SignaturePad } from '../../../components';\nimport type { SignaturePadHandle } from '../../../components/signature-pad';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { SignaturePad } from 'fluxo-ui';\nimport type { SignaturePadHandle } from 'fluxo-ui';\n\nconst ref = useRef<SignaturePadHandle>(null);\n\n<SignaturePad ref={ref} onChange={(empty) => setEmpty(empty)} />\n<Button label=\"Export PNG\" onClick={() => console.log(ref.current?.toDataURL())} />`;\n\nconst BasicUsage: React.FC = () => {\n    const ref = useRef<SignaturePadHandle>(null);\n    const [preview, setPreview] = useState<string | null>(null);\n\n    const handleExport = () => {\n        if (ref.current && !ref.current.isEmpty()) {\n            setPreview(ref.current.toDataURL('image/png'));\n        }\n    };\n\n    return (\n        <>\n            <ComponentDemo title=\"Basic Signature\" description=\"Sign with mouse, touch, or stylus. Use the ref to export.\">\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16, alignItems: 'flex-start' }}>\n                    <SignaturePad ref={ref} onEnd={() => undefined} />\n                    <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>\n                        <Button label=\"Export PNG\" variant=\"primary\" size=\"sm\" onClick={handleExport} />\n                        <Button label=\"Clear\" size=\"sm\" layout=\"outlined\" onClick={() => { ref.current?.clear(); setPreview(null); }} />\n                    </div>\n                    {preview && (\n                        <div style={{ padding: '10px 14px', background: 'var(--eui-bg-subtle)', border: '1px solid var(--eui-border-subtle)', borderRadius: 6 }}>\n                            <div style={{ fontSize: 12, color: 'var(--eui-text-muted)', marginBottom: 6 }}>Exported PNG:</div>\n                            <img src={preview} alt=\"Signature\" style={{ maxHeight: 80, background: '#fff', borderRadius: 4 }} />\n                        </div>\n                    )}\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "Variants",
          "code": "import React from 'react';\nimport { SignaturePad } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<SignaturePad border=\"dashed\" background=\"grid\" />\n<SignaturePad border=\"solid\" background=\"dotted\" penColor=\"#2563eb\" thickness=\"bold\" />\n<SignaturePad border=\"none\" background=\"white\" thickness=\"thin\" />`;\n\nconst Variants: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Borders, Backgrounds & Pen Variants\" description=\"Mix border styles, backgrounds, pen colors, and thicknesses.\">\n            <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 20 }}>\n                <div>\n                    <div style={{ fontSize: 12, marginBottom: 6, color: 'var(--eui-text-muted)' }}>Dashed border · grid background</div>\n                    <SignaturePad border=\"dashed\" background=\"grid\" size=\"md\" />\n                </div>\n                <div>\n                    <div style={{ fontSize: 12, marginBottom: 6, color: 'var(--eui-text-muted)' }}>Dotted background · bold blue pen</div>\n                    <SignaturePad border=\"solid\" background=\"dotted\" penColor=\"#2563eb\" thickness=\"bold\" size=\"md\" />\n                </div>\n                <div>\n                    <div style={{ fontSize: 12, marginBottom: 6, color: 'var(--eui-text-muted)' }}>No border · thin pen · with color swatches</div>\n                    <SignaturePad border=\"none\" background=\"white\" thickness=\"thin\" size=\"md\" showSwatches />\n                </div>\n                <div>\n                    <div style={{ fontSize: 12, marginBottom: 6, color: 'var(--eui-text-muted)' }}>Full width</div>\n                    <SignaturePad size=\"full\" border=\"dashed\" background=\"grid\" />\n                </div>\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default Variants;\n"
        }
      ],
      "props": {
        "sigProps": {
          "size": {
            "type": "'sm' | 'md' | 'lg' | 'full'",
            "default": "'md'",
            "description": "Canvas size preset."
          },
          "border": {
            "type": "'solid' | 'dashed' | 'none'",
            "default": "'solid'",
            "description": "Border style."
          },
          "background": {
            "type": "'white' | 'transparent' | 'grid' | 'dotted'",
            "default": "'white'",
            "description": "Canvas background pattern."
          },
          "penColor": {
            "type": "string",
            "default": "'#111827'",
            "description": "Ink color."
          },
          "thickness": {
            "type": "'thin' | 'regular' | 'bold' | number",
            "default": "'regular'",
            "description": "Pen thickness."
          },
          "showToolbar": {
            "type": "boolean",
            "default": "true",
            "description": "Show Undo/Clear buttons."
          },
          "showSwatches": {
            "type": "boolean",
            "default": "false",
            "description": "Show color swatches in the toolbar."
          },
          "swatches": {
            "type": "string[]",
            "description": "Custom color swatches."
          },
          "placeholder": {
            "type": "string",
            "default": "'Sign here'",
            "description": "Placeholder text shown when empty."
          },
          "allowTypeMode": {
            "type": "boolean",
            "default": "true",
            "description": "Show a Draw/Type tab so users who cannot draw can type their name as the signature."
          },
          "typeFontFamily": {
            "type": "string",
            "default": "'Brush Script MT, Lucida Handwriting, Apple Chancery, cursive'",
            "description": "Font family used to render the typed signature on the canvas."
          },
          "ariaLabel": {
            "type": "string",
            "default": "'Signature pad'",
            "description": "Base accessible name for the canvas. Empty/has-signature state is appended automatically."
          },
          "onBegin": {
            "type": "() => void",
            "description": "Called at stroke start."
          },
          "onEnd": {
            "type": "() => void",
            "description": "Called at stroke end."
          },
          "onChange": {
            "type": "(isEmpty: boolean) => void",
            "description": "Called whenever empty state flips."
          }
        }
      },
      "storyDir": "signature-pad"
    },
    "Slider": {
      "name": "Slider",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React, { useState } from 'react';\nimport { Slider } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { Slider } from 'fluxo-ui';\n\nconst [value, setValue] = useState(40);\n\n<Slider\n  value={value}\n  onChange={(v) => setValue(v as number)}\n  showTooltip\n/>\n\n<Slider defaultValue={60} showMinMax />\n\n<Slider defaultValue={25} showValue valuePosition=\"right\" />`;\n\nconst BasicUsage: React.FC = () => {\n    const [value, setValue] = useState(40);\n\n    return (\n        <>\n            <ComponentDemo title=\"Default Slider\" description=\"A simple slider with controlled value and tooltip on hover.\">\n                <div className=\"space-y-8 w-full max-w-lg\">\n                    <div>\n                        <div className=\"text-sm mb-2 opacity-70\">Controlled with tooltip (value: {value})</div>\n                        <Slider value={value} onChange={(v) => setValue(v as number)} showTooltip />\n                    </div>\n                    <div>\n                        <div className=\"text-sm mb-2 opacity-70\">Uncontrolled with min/max labels</div>\n                        <Slider defaultValue={60} showMinMax />\n                    </div>\n                    <div>\n                        <div className=\"text-sm mb-2 opacity-70\">With value display on the right</div>\n                        <Slider defaultValue={25} showValue valuePosition=\"right\" />\n                    </div>\n                    <div>\n                        <div className=\"text-sm mb-2 opacity-70\">Disabled slider</div>\n                        <Slider defaultValue={50} disabled showMinMax />\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "Formatting",
          "code": "import React, { useState } from 'react';\nimport { Slider } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { Slider } from 'fluxo-ui';\n\n// Currency formatting\n<Slider\n  min={0}\n  max={1000}\n  step={10}\n  defaultValue={500}\n  showTooltip=\"always\"\n  tooltipFormat={(v) => \\`$\\${v}\\`}\n  valueFormat={(v) => \\`$\\${v.toLocaleString()}\\`}\n  showValue\n  valuePosition=\"top\"\n/>\n\n// Percentage formatting\n<Slider\n  defaultValue={65}\n  showTooltip=\"always\"\n  tooltipFormat={(v) => \\`\\${v}%\\`}\n  showMinMax\n/>\n\n// Temperature with unit\n<Slider\n  min={-20}\n  max={50}\n  defaultValue={22}\n  showTooltip\n  tooltipFormat={(v) => \\`\\${v}°F\\`}\n  showValue\n  valuePosition=\"right\"\n  valueFormat={(v) => \\`\\${v}°F\\`}\n/>`;\n\nconst Formatting: React.FC = () => {\n    const [currency, setCurrency] = useState(500);\n    const [percent, setPercent] = useState(65);\n\n    return (\n        <>\n            <ComponentDemo title=\"Value Formatting\" description=\"Use tooltipFormat and valueFormat to customize how values are displayed.\">\n                <div className=\"space-y-10 w-full max-w-lg\">\n                    <div>\n                        <div className=\"text-sm mb-2 opacity-70\">Currency format</div>\n                        <Slider\n                            min={0}\n                            max={1000}\n                            step={10}\n                            value={currency}\n                            onChange={(v) => setCurrency(v as number)}\n                            showTooltip=\"always\"\n                            tooltipFormat={(v) => `$${v}`}\n                            valueFormat={(v) => `$${v.toLocaleString()}`}\n                            showValue\n                            valuePosition=\"top\"\n                            variant=\"success\"\n                        />\n                    </div>\n                    <div>\n                        <div className=\"text-sm mb-2 opacity-70\">Percentage format</div>\n                        <Slider\n                            value={percent}\n                            onChange={(v) => setPercent(v as number)}\n                            showTooltip=\"always\"\n                            tooltipFormat={(v) => `${v}%`}\n                            showMinMax\n                            variant=\"primary\"\n                        />\n                    </div>\n                    <div>\n                        <div className=\"text-sm mb-2 opacity-70\">Temperature with unit</div>\n                        <Slider\n                            min={-20}\n                            max={50}\n                            defaultValue={22}\n                            showTooltip\n                            tooltipFormat={(v) => `${v}\\u00B0F`}\n                            showValue\n                            valuePosition=\"right\"\n                            valueFormat={(v) => `${v}\\u00B0F`}\n                            variant=\"danger\"\n                        />\n                    </div>\n                    <div>\n                        <div className=\"text-sm mb-2 opacity-70\">Time duration (minutes)</div>\n                        <Slider\n                            min={0}\n                            max={120}\n                            step={5}\n                            defaultValue={45}\n                            showTooltip=\"always\"\n                            tooltipFormat={(v) => {\n                                const hrs = Math.floor(v / 60);\n                                const mins = v % 60;\n                                return hrs > 0 ? `${hrs}h ${mins}m` : `${mins}m`;\n                            }}\n                            showValue\n                            valuePosition=\"top\"\n                            valueFormat={(v) => {\n                                const hrs = Math.floor(v / 60);\n                                const mins = v % 60;\n                                return hrs > 0 ? `${hrs}h ${mins}m` : `${mins}m`;\n                            }}\n                            variant=\"info\"\n                        />\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default Formatting;\n"
        },
        {
          "title": "GridSnap",
          "code": "import React, { useState } from 'react';\nimport { Slider } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { Slider } from 'fluxo-ui';\n\n// Snap to step with smooth animation\n<Slider\n  defaultValue={50}\n  snap\n  step={10}\n  marks\n  showTooltip\n/>\n\n// Grid step with custom duration\n<Slider\n  defaultValue={0}\n  gridStep={25}\n  gridDuration={200}\n  marks\n  showTooltip=\"always\"\n  variant=\"success\"\n/>`;\n\nconst GridSnap: React.FC = () => {\n    const [snapValue, setSnapValue] = useState(50);\n    const [gridValue, setGridValue] = useState(0);\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Grid & Snap Behavior\"\n                description=\"Enable snap for step-based snapping, or use gridStep for coarser grid alignment with animated transitions.\"\n            >\n                <div className=\"space-y-10 w-full max-w-lg\">\n                    <div>\n                        <div className=\"text-sm mb-2 opacity-70\">Snap to step=10 (value: {snapValue})</div>\n                        <Slider value={snapValue} onChange={(v) => setSnapValue(v as number)} snap step={10} marks showTooltip />\n                    </div>\n                    <div>\n                        <div className=\"text-sm mb-2 opacity-70\">Grid step=25 with animation (value: {gridValue})</div>\n                        <Slider\n                            value={gridValue}\n                            onChange={(v) => setGridValue(v as number)}\n                            gridStep={25}\n                            gridDuration={200}\n                            marks\n                            showTooltip=\"always\"\n                            variant=\"success\"\n                        />\n                    </div>\n                    <div>\n                        <div className=\"text-sm mb-2 opacity-70\">Snap to step=5 with no fill</div>\n                        <Slider defaultValue={30} snap step={5} marks filled={false} showTooltip variant=\"info\" />\n                    </div>\n                    <div>\n                        <div className=\"text-sm mb-2 opacity-70\">Grid step=20, range mode</div>\n                        <Slider\n                            range\n                            defaultRangeValue={[20, 60]}\n                            gridStep={20}\n                            gridDuration={150}\n                            marks\n                            showTooltip=\"always\"\n                            variant=\"warning\"\n                        />\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default GridSnap;\n"
        },
        {
          "title": "RangeSlider",
          "code": "import React, { useState } from 'react';\nimport { Slider } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { Slider } from 'fluxo-ui';\n\nconst [range, setRange] = useState<[number, number]>([20, 80]);\n\n<Slider\n  range\n  rangeValue={range}\n  onChange={(v) => setRange(v as [number, number])}\n  showTooltip=\"always\"\n  showMinMax\n/>\n\n<Slider\n  range\n  defaultRangeValue={[1000, 5000]}\n  min={0}\n  max={10000}\n  step={100}\n  showValue\n  valuePosition=\"top\"\n  valueFormat={(v) => \\`$\\${v.toLocaleString()}\\`}\n/>`;\n\nconst RangeSlider: React.FC = () => {\n    const [range, setRange] = useState<[number, number]>([20, 80]);\n    const [priceRange, setPriceRange] = useState<[number, number]>([1000, 5000]);\n\n    return (\n        <>\n            <ComponentDemo title=\"Range Slider\" description=\"Use the range prop for dual-thumb selection of a value range.\">\n                <div className=\"space-y-8 w-full max-w-lg\">\n                    <div>\n                        <div className=\"text-sm mb-2 opacity-70\">\n                            Basic range ({range[0]} - {range[1]})\n                        </div>\n                        <Slider\n                            range\n                            rangeValue={range}\n                            onChange={(v) => setRange(v as [number, number])}\n                            showTooltip=\"always\"\n                            showMinMax\n                        />\n                    </div>\n                    <div>\n                        <div className=\"text-sm mb-2 opacity-70\">Price range filter</div>\n                        <Slider\n                            range\n                            rangeValue={priceRange}\n                            onChange={(v) => setPriceRange(v as [number, number])}\n                            min={0}\n                            max={10000}\n                            step={100}\n                            showValue\n                            valuePosition=\"top\"\n                            valueFormat={(v) => `$${v.toLocaleString()}`}\n                        />\n                    </div>\n                    <div>\n                        <div className=\"text-sm mb-2 opacity-70\">Range with marks</div>\n                        <Slider range defaultRangeValue={[25, 75]} marks step={25} showTooltip />\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default RangeSlider;\n"
        },
        {
          "title": "Sizes",
          "code": "import React from 'react';\nimport type { SliderSize } from '../../../components';\nimport { Slider } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { Slider } from 'fluxo-ui';\nimport type { SliderSize } from 'fluxo-ui';\n\nconst sizes: SliderSize[] = ['xs', 'sm', 'md', 'lg', 'xl'];\n\n{sizes.map((size) => (\n  <Slider key={size} size={size} defaultValue={50} showTooltip />\n))}`;\n\nconst sizes: { size: SliderSize; label: string }[] = [\n    { size: 'xs', label: 'Extra Small' },\n    { size: 'sm', label: 'Small' },\n    { size: 'md', label: 'Medium (default)' },\n    { size: 'lg', label: 'Large' },\n    { size: 'xl', label: 'Extra Large' },\n];\n\nconst Sizes: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo title=\"Slider Sizes\" description=\"Five size options control the track height, thumb size, and font size.\">\n                <div className=\"space-y-6 w-full max-w-lg\">\n                    {sizes.map(({ size, label }) => (\n                        <div key={size}>\n                            <div className=\"text-sm mb-2 opacity-70\">\n                                {label} ({size})\n                            </div>\n                            <Slider size={size} defaultValue={50} showTooltip showMinMax />\n                        </div>\n                    ))}\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default Sizes;\n"
        },
        {
          "title": "StringValues",
          "code": "import React, { useState } from 'react';\nimport { Slider } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { Slider } from 'fluxo-ui';\n\nconst months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',\n  'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];\n\n<Slider\n  labels={months}\n  defaultValue={3}\n  marks\n  showTooltip=\"always\"\n/>\n\nconst sizes = ['XS', 'S', 'M', 'L', 'XL', 'XXL'];\n\n<Slider\n  labels={sizes}\n  defaultValue={2}\n  marks\n  showValue\n  valuePosition=\"top\"\n/>`;\n\nconst months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];\nconst clothingSizes = ['XS', 'S', 'M', 'L', 'XL', 'XXL'];\nconst priorities = ['Low', 'Medium', 'High', 'Critical'];\n\nconst StringValues: React.FC = () => {\n    const [monthIndex, setMonthIndex] = useState(3);\n    const [sizeIndex, setSizeIndex] = useState(2);\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"String Labels\"\n                description=\"Use the labels prop to map slider positions to string values like months or sizes.\"\n            >\n                <div className=\"space-y-10 w-full max-w-lg\">\n                    <div>\n                        <div className=\"text-sm mb-2 opacity-70\">Month selector (selected: {months[monthIndex]})</div>\n                        <Slider\n                            labels={months}\n                            value={monthIndex}\n                            onChange={(v) => setMonthIndex(v as number)}\n                            marks\n                            showTooltip=\"always\"\n                        />\n                    </div>\n                    <div>\n                        <div className=\"text-sm mb-2 opacity-70\">Clothing size (selected: {clothingSizes[sizeIndex]})</div>\n                        <Slider\n                            labels={clothingSizes}\n                            value={sizeIndex}\n                            onChange={(v) => setSizeIndex(v as number)}\n                            marks\n                            showValue\n                            valuePosition=\"right\"\n                            variant=\"info\"\n                        />\n                    </div>\n                    <div>\n                        <div className=\"text-sm mb-2 opacity-70\">Priority level</div>\n                        <Slider labels={priorities} defaultValue={1} marks showTooltip variant=\"warning\" size=\"lg\" />\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default StringValues;\n"
        },
        {
          "title": "Variants",
          "code": "import React from 'react';\nimport type { SliderVariant } from '../../../components';\nimport { Slider } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { Slider } from 'fluxo-ui';\nimport type { SliderVariant } from 'fluxo-ui';\n\nconst variants: SliderVariant[] = [\n  'default', 'primary', 'success', 'warning', 'danger', 'info'\n];\n\n{variants.map((variant) => (\n  <Slider key={variant} variant={variant} defaultValue={60} />\n))}`;\n\nconst variants: { variant: SliderVariant; label: string; defaultVal: number }[] = [\n    { variant: 'default', label: 'Default', defaultVal: 45 },\n    { variant: 'primary', label: 'Primary', defaultVal: 55 },\n    { variant: 'success', label: 'Success', defaultVal: 65 },\n    { variant: 'warning', label: 'Warning', defaultVal: 50 },\n    { variant: 'danger', label: 'Danger', defaultVal: 40 },\n    { variant: 'info', label: 'Info', defaultVal: 70 },\n];\n\nconst Variants: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo title=\"Color Variants\" description=\"Six color variants for different semantic purposes.\">\n                <div className=\"space-y-6 w-full max-w-lg\">\n                    {variants.map(({ variant, label, defaultVal }) => (\n                        <div key={variant}>\n                            <div className=\"text-sm mb-2 opacity-70\">{label}</div>\n                            <Slider variant={variant} defaultValue={defaultVal} showTooltip />\n                        </div>\n                    ))}\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default Variants;\n"
        },
        {
          "title": "VerticalSlider",
          "code": "import React, { useState } from 'react';\nimport { Slider } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { Slider } from 'fluxo-ui';\n\n<Slider\n  orientation=\"vertical\"\n  defaultValue={60}\n  showTooltip\n/>\n\n<Slider\n  orientation=\"vertical\"\n  range\n  defaultRangeValue={[20, 80]}\n  showTooltip=\"always\"\n  variant=\"success\"\n/>`;\n\nconst VerticalSlider: React.FC = () => {\n    const [value, setValue] = useState(60);\n\n    return (\n        <>\n            <ComponentDemo title=\"Vertical Orientation\" description=\"Set orientation to vertical for a top-to-bottom slider.\">\n                <div className=\"flex flex-wrap gap-8 md:gap-12 items-end\" style={{ height: 250 }}>\n                    <div className=\"flex flex-col items-center gap-2\">\n                        <Slider orientation=\"vertical\" value={value} onChange={(v) => setValue(v as number)} showTooltip />\n                        <span className=\"text-xs opacity-70\">Default</span>\n                    </div>\n                    <div className=\"flex flex-col items-center gap-2\">\n                        <Slider orientation=\"vertical\" defaultValue={40} variant=\"success\" showTooltip showMinMax />\n                        <span className=\"text-xs opacity-70\">Success</span>\n                    </div>\n                    <div className=\"flex flex-col items-center gap-2\">\n                        <Slider orientation=\"vertical\" defaultValue={75} variant=\"warning\" size=\"lg\" showTooltip />\n                        <span className=\"text-xs opacity-70\">Large</span>\n                    </div>\n                    <div className=\"flex flex-col items-center gap-2\">\n                        <Slider orientation=\"vertical\" range defaultRangeValue={[20, 80]} variant=\"info\" showTooltip=\"always\" />\n                        <span className=\"text-xs opacity-70\">Range</span>\n                    </div>\n                    <div className=\"flex flex-col items-center gap-2\">\n                        <Slider orientation=\"vertical\" defaultValue={50} disabled />\n                        <span className=\"text-xs opacity-70\">Disabled</span>\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default VerticalSlider;\n"
        },
        {
          "title": "WithMarks",
          "code": "import React from 'react';\nimport { Slider } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { Slider } from 'fluxo-ui';\n\n// Auto-generated marks based on step\n<Slider defaultValue={50} marks step={10} showTooltip />\n\n// Custom marks with labels\n<Slider\n  defaultValue={37}\n  min={0}\n  max={100}\n  marks={[\n    { value: 0, label: '0°C' },\n    { value: 25, label: '25°C' },\n    { value: 37, label: '37°C' },\n    { value: 50, label: '50°C' },\n    { value: 75, label: '75°C' },\n    { value: 100, label: '100°C' },\n  ]}\n  showTooltip\n  variant=\"danger\"\n/>`;\n\nconst temperatureMarks = [\n    { value: 0, label: '0\\u00B0C' },\n    { value: 25, label: '25\\u00B0C' },\n    { value: 37, label: '37\\u00B0C' },\n    { value: 50, label: '50\\u00B0C' },\n    { value: 75, label: '75\\u00B0C' },\n    { value: 100, label: '100\\u00B0C' },\n];\n\nconst percentMarks = [\n    { value: 0, label: '0%' },\n    { value: 25, label: '25%' },\n    { value: 50, label: '50%' },\n    { value: 75, label: '75%' },\n    { value: 100, label: '100%' },\n];\n\nconst WithMarks: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo\n                title=\"Slider with Marks\"\n                description=\"Display marks along the track using auto-generated or custom mark definitions.\"\n            >\n                <div className=\"space-y-10 w-full max-w-lg\">\n                    <div>\n                        <div className=\"text-sm mb-2 opacity-70\">Auto marks (step=25)</div>\n                        <Slider defaultValue={50} marks step={25} showTooltip />\n                    </div>\n                    <div>\n                        <div className=\"text-sm mb-2 opacity-70\">Temperature marks</div>\n                        <Slider\n                            defaultValue={37}\n                            min={0}\n                            max={100}\n                            marks={temperatureMarks}\n                            showTooltip\n                            variant=\"danger\"\n                            tooltipFormat={(v) => `${v}\\u00B0C`}\n                        />\n                    </div>\n                    <div>\n                        <div className=\"text-sm mb-2 opacity-70\">Percentage marks with range</div>\n                        <Slider range defaultRangeValue={[25, 75]} marks={percentMarks} showTooltip variant=\"success\" />\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default WithMarks;\n"
        }
      ],
      "props": {
        "sliderProps": {
          "value": {
            "type": "number",
            "description": "Controlled value of the slider."
          },
          "defaultValue": {
            "type": "number",
            "default": "0",
            "description": "Initial value for uncontrolled usage."
          },
          "min": {
            "type": "number",
            "default": "0",
            "description": "Minimum value."
          },
          "max": {
            "type": "number",
            "default": "100",
            "description": "Maximum value."
          },
          "step": {
            "type": "number",
            "default": "1",
            "description": "Step increment between values."
          },
          "orientation": {
            "type": "'horizontal' | 'vertical'",
            "default": "'horizontal'",
            "description": "Slider axis direction."
          },
          "size": {
            "type": "'xs' | 'sm' | 'md' | 'lg' | 'xl'",
            "default": "'md'",
            "description": "Size of the track and thumb."
          },
          "variant": {
            "type": "'default' | 'primary' | 'success' | 'warning' | 'danger' | 'info'",
            "default": "'primary'",
            "description": "Color variant."
          },
          "disabled": {
            "type": "boolean",
            "default": "false",
            "description": "Disable interaction."
          },
          "range": {
            "type": "boolean",
            "default": "false",
            "description": "Enable dual-thumb range mode."
          },
          "rangeValue": {
            "type": "[number, number]",
            "description": "Controlled range value (low, high)."
          },
          "defaultRangeValue": {
            "type": "[number, number]",
            "description": "Initial range value for uncontrolled usage."
          },
          "marks": {
            "type": "SliderMark[] | boolean",
            "description": "Display marks on the track. Pass true for auto-generated marks or an array for custom marks."
          },
          "showTooltip": {
            "type": "boolean | 'always'",
            "default": "false",
            "description": "Show tooltip on hover/drag or always."
          },
          "tooltipFormat": {
            "type": "(value: number) => string",
            "description": "Custom formatter for tooltip text."
          },
          "valueFormat": {
            "type": "(value: number) => string",
            "description": "Custom formatter for displayed value."
          },
          "showValue": {
            "type": "boolean",
            "default": "false",
            "description": "Display the current value alongside the slider."
          },
          "valuePosition": {
            "type": "'top' | 'bottom' | 'left' | 'right'",
            "default": "'top'",
            "description": "Position of the displayed value."
          },
          "snap": {
            "type": "boolean",
            "default": "false",
            "description": "Snap the thumb to the nearest step."
          },
          "gridStep": {
            "type": "number",
            "description": "Coarser step for grid-based snapping."
          },
          "gridDuration": {
            "type": "number",
            "default": "150",
            "description": "Animation duration (ms) for grid snap transitions."
          },
          "labels": {
            "type": "string[]",
            "description": "Map slider positions to string labels. Min/max auto-set from array length."
          },
          "showMinMax": {
            "type": "boolean",
            "default": "false",
            "description": "Show min and max labels at the ends."
          },
          "trackHeight": {
            "type": "number",
            "description": "Override the track height/width in pixels."
          },
          "thumbSize": {
            "type": "number",
            "description": "Override the thumb size in pixels."
          },
          "filled": {
            "type": "boolean",
            "default": "true",
            "description": "Show a filled track from min to current value."
          },
          "onChange": {
            "type": "(value: number | [number, number]) => void",
            "description": "Called on every value change during interaction."
          },
          "onChangeEnd": {
            "type": "(value: number | [number, number]) => void",
            "description": "Called when interaction ends (pointer up or keyboard)."
          },
          "name": {
            "type": "string",
            "description": "When set, renders hidden form inputs so the slider value submits with surrounding forms. Range mode produces `${name}_min` and `${name}_max`."
          },
          "rangeStartLabel": {
            "type": "string",
            "default": "'Minimum'",
            "description": "ARIA label for the lower thumb in range mode (helps screen readers distinguish thumbs)."
          },
          "rangeEndLabel": {
            "type": "string",
            "default": "'Maximum'",
            "description": "ARIA label for the upper thumb in range mode."
          }
        }
      },
      "storyDir": "slider"
    },
    "Snackbar": {
      "name": "Snackbar",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "AnimationsDemo",
          "code": "import React from 'react';\nimport { Button, showSnackbar } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst animations = ['slide', 'fade', 'zoom', 'bounce'] as const;\n\nconst code = `showSnackbar('Done!', 'Success', { type: 'success', animation: 'bounce' });`;\n\nconst AnimationsDemo: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo title=\"Entry animations\" description=\"Each snackbar supports different entry/exit animations.\">\n                <div className=\"flex gap-3 flex-wrap\">\n                    {animations.map((animation) => (\n                        <Button\n                            key={animation}\n                            variant=\"primary\"\n                            layout=\"outlined\"\n                            size=\"sm\"\n                            onClick={() => {\n                                showSnackbar(`Animation: ${animation}`, 'Demo', { type: 'success', animation });\n                            }}\n                        >\n                            {animation}\n                        </Button>\n                    ))}\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default AnimationsDemo;\n"
        },
        {
          "title": "ClickCallback",
          "code": "import React from 'react';\nimport { Button, showSnackbar } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `showSnackbar('3 new messages received. Click to view.', 'Messages', {\n  type: 'info',\n  timeout: 6000,\n  onClick: () => navigate('/messages'),\n  onClose: (manual) => console.log('closed by user:', manual),\n});`;\n\nconst ClickCallback: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo title=\"Clickable snackbar\" description=\"Attach onClick to handle user interaction (e.g., navigate to details).\">\n                <Button\n                    variant=\"primary\"\n                    onClick={() => {\n                        showSnackbar('3 new messages received. Click to view.', 'Messages', {\n                            type: 'info',\n                            timeout: 6000,\n                            onClick: () => console.log('Navigating to messages...'),\n                        });\n                    }}\n                >\n                    Show Clickable Snackbar\n                </Button>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default ClickCallback;\n"
        },
        {
          "title": "PersistentTimeout",
          "code": "import React from 'react';\nimport { Button, showSnackbar } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `showSnackbar('Critical error occurred.', 'Error', {\n  type: 'error',\n  timeout: 0,\n  showCloseButton: true,\n});`;\n\nconst PersistentTimeout: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo title=\"Timeout control\" description=\"Set timeout to 0 for a persistent snackbar that only dismisses manually.\">\n                <div className=\"flex gap-3 flex-wrap\">\n                    <Button\n                        variant=\"warning\"\n                        onClick={() => {\n                            showSnackbar('This will not auto-dismiss. Click \\u00d7 to close.', 'Persistent', {\n                                type: 'warning',\n                                timeout: 0,\n                                showCloseButton: true,\n                            });\n                        }}\n                    >\n                        Persistent (no auto-dismiss)\n                    </Button>\n                    <Button\n                        variant=\"success\"\n                        layout=\"outlined\"\n                        onClick={() => {\n                            showSnackbar('Dismisses in 1.5 seconds.', 'Fast', {\n                                type: 'success',\n                                timeout: 1500,\n                            });\n                        }}\n                    >\n                        1.5s Timeout\n                    </Button>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default PersistentTimeout;\n"
        },
        {
          "title": "PositionsDemo",
          "code": "import React from 'react';\nimport { Button, showSnackbar } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst positions = ['topLeft', 'topCenter', 'topRight', 'bottomLeft', 'bottomCenter', 'bottomRight'] as const;\n\nconst code = `showSnackbar('Saved!', 'Success', { type: 'success', position: 'topRight' });`;\n\nconst PositionsDemo: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo title=\"Screen positions\" description=\"Click a position to see the snackbar appear there.\">\n                <div className=\"grid grid-cols-2 sm:grid-cols-3 gap-3\">\n                    {positions.map((position) => (\n                        <Button\n                            key={position}\n                            variant=\"secondary\"\n                            layout=\"outlined\"\n                            size=\"sm\"\n                            onClick={() => {\n                                showSnackbar(`Placed at ${position}`, 'Position Demo', { position, type: 'info' });\n                            }}\n                        >\n                            {position}\n                        </Button>\n                    ))}\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default PositionsDemo;\n"
        },
        {
          "title": "SetupSection",
          "code": "import React from 'react';\nimport { CodeBlock } from '../../CodeBlock';\n\nconst code = `import { SnackbarManager } from 'fluxo-ui';\n\nfunction App() {\n  return (\n    <>\n      <SnackbarManager />\n      {/* rest of app */}\n    </>\n  );\n}`;\n\nconst defaultsCode = `// Set app-wide defaults once; any showSnackbar() call can still override them\n<SnackbarManager defaultOptions={{ variant: 'soft', size: 'sm', position: 'bottomRight' }} />\n\n// Uses the manager defaults (soft, sm, bottomRight)\nshowSnackbar('Saved');\n\n// Overrides size + position just for this call\nshowSnackbar('Upload failed', 'Error', { type: 'error', size: 'md', position: 'topCenter' });`;\n\nconst SetupSection: React.FC = () => {\n    return (\n        <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>\n            <CodeBlock title=\"App root\" code={code} />\n            <CodeBlock title=\"Manager defaults (overridable per call)\" code={defaultsCode} />\n        </div>\n    );\n};\n\nexport default SetupSection;\n"
        },
        {
          "title": "SizesDemo",
          "code": "import React from 'react';\nimport { Button, showSnackbar } from '../../../components';\nimport type { SnackbarSize } from '../../../components/snackbar/types';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst sizes: { size: SnackbarSize; label: string }[] = [\n    { size: 'sm', label: 'Small' },\n    { size: 'md', label: 'Medium' },\n    { size: 'lg', label: 'Large' },\n];\n\nconst code = `showSnackbar('Compact and short.', 'Small', { size: 'sm', variant: 'soft', type: 'info' });\nshowSnackbar('The default footprint.', 'Medium', { size: 'md', variant: 'soft', type: 'info' });\nshowSnackbar('Roomier for richer messages.', 'Large', { size: 'lg', variant: 'soft', type: 'info' });`;\n\nconst SizesDemo: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo\n                title=\"Sizes\"\n                description=\"An orthogonal size scale. sm gives a noticeably shorter snackbar and combines with any variant.\"\n            >\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16 }}>\n                    <div className=\"flex gap-3 flex-wrap\">\n                        {sizes.map(({ size, label }) => (\n                            <Button\n                                key={size}\n                                variant=\"secondary\"\n                                size={size}\n                                onClick={() => {\n                                    showSnackbar(`The ${label.toLowerCase()} snackbar size.`, label, {\n                                        size,\n                                        variant: 'soft',\n                                        type: 'info',\n                                    });\n                                }}\n                            >\n                                {label}\n                            </Button>\n                        ))}\n                    </div>\n                    <div\n                        style={{\n                            padding: '12px 16px',\n                            background: 'var(--eui-bg-subtle)',\n                            border: '1px solid var(--eui-border-subtle)',\n                            borderRadius: 6,\n                            fontSize: 13,\n                            color: 'var(--eui-text-muted)',\n                        }}\n                    >\n                        Pair <strong style={{ color: 'var(--eui-text)' }}>size: 'sm'</strong> with{' '}\n                        <strong style={{ color: 'var(--eui-text)' }}>variant: 'minimal'</strong> for the most compact, shortest\n                        notification.\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default SizesDemo;\n"
        },
        {
          "title": "TypesDemo",
          "code": "import React from 'react';\nimport { Button, showSnackbar } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst types = ['info', 'success', 'warning', 'error'] as const;\n\nconst code = `showSnackbar('File uploaded successfully.', 'Success', { type: 'success' });\nshowSnackbar('Disk usage is high.', 'Warning', { type: 'warning' });\nshowSnackbar('Connection failed.', 'Error', { type: 'error' });\nshowSnackbar('3 new messages arrived.', 'Info', { type: 'info' });`;\n\nconst TypesDemo: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo title=\"Notification types\" description=\"Four semantic types with distinct colors and icons.\">\n                <div className=\"flex gap-3 flex-wrap\">\n                    {types.map((type) => (\n                        <Button\n                            key={type}\n                            variant={type === 'info' ? 'primary' : type === 'success' ? 'success' : type === 'warning' ? 'warning' : 'danger'}\n                            onClick={() => {\n                                showSnackbar(`This is a ${type} notification`, `${type.charAt(0).toUpperCase() + type.slice(1)}`, { type });\n                            }}\n                        >\n                            {type.charAt(0).toUpperCase() + type.slice(1)}\n                        </Button>\n                    ))}\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default TypesDemo;\n"
        },
        {
          "title": "VariantsDemo",
          "code": "import React from 'react';\nimport { Button, showSnackbar } from '../../../components';\nimport type { SnackbarVariant } from '../../../components/snackbar/types';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst variants: { variant: SnackbarVariant; label: string; description: string }[] = [\n    { variant: 'soft', label: 'Soft', description: 'A gently tinted surface with a colored title and icon. The default.' },\n    { variant: 'solid', label: 'Solid', description: 'A bold filled card in the type color with white text.' },\n    { variant: 'outlined', label: 'Outlined', description: 'A clean surface card framed by an accent ring.' },\n    { variant: 'gradient', label: 'Gradient', description: 'A vivid diagonal fill in the type color with white text.' },\n    { variant: 'accent', label: 'Accent', description: 'A surface card topped with a bold colored bar.' },\n    { variant: 'glass', label: 'Glass', description: 'A frosted, translucent panel that blurs the backdrop.' },\n    { variant: 'minimal', label: 'Minimal', description: 'A compact single-line chip — the shortest height.' },\n    { variant: 'pill', label: 'Pill', description: 'A rounded single-line badge in the solid type color.' },\n];\n\nconst code = `showSnackbar('A new version is available.', 'Update', { variant: 'soft', type: 'info' });\nshowSnackbar('Your changes have been saved.', 'Saved', { variant: 'solid', type: 'success' });\nshowSnackbar('Storage is almost full.', 'Heads up', { variant: 'accent', type: 'warning' });\nshowSnackbar('Copied to clipboard', undefined, { variant: 'pill', type: 'success' });\nshowSnackbar('Reconnecting…', undefined, { variant: 'minimal', type: 'info' });`;\n\nconst VariantsDemo: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo\n                title=\"Visual variants\"\n                description=\"Eight looks share the same API. Single-line variants (minimal, pill) drop the title for a shorter footprint.\"\n            >\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16 }}>\n                    <div className=\"flex gap-3 flex-wrap\">\n                        {variants.map(({ variant, label }, index) => (\n                            <Button\n                                key={variant}\n                                variant={index % 2 === 0 ? 'primary' : 'secondary'}\n                                onClick={() => {\n                                    showSnackbar(`This is the ${label.toLowerCase()} variant.`, label, {\n                                        variant,\n                                        type: 'info',\n                                    });\n                                }}\n                            >\n                                {label}\n                            </Button>\n                        ))}\n                    </div>\n                    <div\n                        style={{\n                            padding: '12px 16px',\n                            background: 'var(--eui-bg-subtle)',\n                            border: '1px solid var(--eui-border-subtle)',\n                            borderRadius: 6,\n                            display: 'flex',\n                            flexDirection: 'column',\n                            gap: 6,\n                        }}\n                    >\n                        {variants.map(({ variant, description }) => (\n                            <div key={variant} style={{ fontSize: 13, color: 'var(--eui-text-muted)' }}>\n                                <strong style={{ color: 'var(--eui-text)' }}>{variant}</strong> — {description}\n                            </div>\n                        ))}\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default VariantsDemo;\n"
        }
      ],
      "props": {
        "snackbarProps": {
          "type": {
            "type": "'info' | 'success' | 'warning' | 'error'",
            "default": "info",
            "description": "Determines the color scheme and default icon of the snackbar."
          },
          "timeout": {
            "type": "number",
            "default": "4000",
            "description": "Auto-dismiss delay in milliseconds. Set to 0 to disable auto-dismiss."
          },
          "animation": {
            "type": "'fade' | 'slide' | 'zoom' | 'bounce'",
            "default": "fade",
            "description": "Entry and exit animation style."
          },
          "position": {
            "type": "'topLeft' | 'topCenter' | 'topRight' | 'bottomLeft' | 'bottomCenter' | 'bottomRight'",
            "default": "topRight",
            "description": "Screen corner / edge where the snackbar appears."
          },
          "variant": {
            "type": "'soft' | 'solid' | 'outlined' | 'gradient' | 'accent' | 'glass' | 'minimal' | 'pill'",
            "default": "soft",
            "description": "Visual look and feel. 'soft' is a tinted surface card with a colored icon/title; 'solid' a filled accent card with white text; 'outlined' a surface card framed by an accent ring; 'gradient' a vivid diagonal fill; 'accent' a surface card with a colored top bar; 'glass' a frosted translucent panel; 'minimal' and 'pill' are compact single-line styles that drop the title."
          },
          "size": {
            "type": "'sm' | 'md' | 'lg'",
            "default": "md",
            "description": "Overall size. 'sm' yields a shorter, more compact snackbar; 'lg' a larger one. Works with any variant."
          },
          "showCloseButton": {
            "type": "boolean",
            "default": "true",
            "description": "Whether to render the dismiss (\\u00d7) button."
          },
          "onClick": {
            "type": "() => void",
            "description": "Callback fired when the user clicks the snackbar body."
          },
          "onClose": {
            "type": "(manual: boolean) => void",
            "description": "Callback fired when the snackbar closes. manual is true when closed by the user."
          },
          "customIcon": {
            "type": "SVGIcon",
            "description": "Override the default type icon with a custom SVG icon component."
          }
        },
        "snackbarManagerProps": {
          "defaultOptions": {
            "type": "SnackbarOptions",
            "description": "Default options applied to every snackbar shown through this manager. Useful for setting an app-wide variant, size, position, or timeout in one place. Any option passed directly to showSnackbar() overrides the matching key here, which in turn overrides the library defaults."
          }
        }
      },
      "storyDir": "snackbar"
    },
    "SplitButton": {
      "name": "SplitButton",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React, { useState } from 'react';\nimport { CopyIcon, EditIcon, ShareIcon, TrashIcon } from '../../../assets/icons';\nimport { SplitButton } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { SplitButton } from 'fluxo-ui';\n\n<SplitButton\n  label=\"Save\"\n  onClick={() => console.log('Save')}\n  items={[\n    { label: 'Save as draft', icon: EditIcon, onClick: () => {} },\n    { label: 'Save and publish', icon: ShareIcon, onClick: () => {} },\n    { divider: true },\n    { label: 'Discard changes', icon: TrashIcon, danger: true, onClick: () => {} },\n  ]}\n/>`;\n\nconst BasicUsage: React.FC = () => {\n    const [last, setLast] = useState<string | null>(null);\n    return (\n        <>\n            <ComponentDemo title=\"Default Split Button\" description=\"Primary action with related actions in a menu.\">\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16, alignItems: 'center' }}>\n                    <SplitButton\n                        label=\"Save\"\n                        onClick={() => setLast('Save')}\n                        items={[\n                            { label: 'Save as draft', icon: EditIcon, onClick: () => setLast('Save as draft') },\n                            { label: 'Save and publish', icon: ShareIcon, onClick: () => setLast('Save and publish') },\n                            { label: 'Duplicate', icon: CopyIcon, shortcut: '⌘D', onClick: () => setLast('Duplicate') },\n                            { divider: true },\n                            { label: 'Discard changes', icon: TrashIcon, danger: true, onClick: () => setLast('Discard changes') },\n                        ]}\n                    />\n                    <div\n                        style={{\n                            padding: '10px 14px',\n                            background: 'var(--eui-bg-subtle)',\n                            border: '1px solid var(--eui-border-subtle)',\n                            borderRadius: 6,\n                            fontSize: 13,\n                            minWidth: 220,\n                            textAlign: 'center',\n                        }}\n                    >\n                        Last action: <strong>{last ?? '—'}</strong>\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "Layouts",
          "code": "import React from 'react';\nimport { SplitButton } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst items = [\n    { label: 'Option A', onClick: () => {} },\n    { label: 'Option B', onClick: () => {} },\n];\n\nconst code = `<SplitButton layout=\"default\" label=\"Default\" variant=\"primary\" items={items} />\n<SplitButton layout=\"outlined\" label=\"Outlined\" variant=\"primary\" items={items} />\n<SplitButton layout=\"rounded\" label=\"Rounded\" variant=\"primary\" items={items} />\n<SplitButton layout=\"sharp\" label=\"Sharp\" variant=\"primary\" items={items} />\n<SplitButton layout=\"plain\" label=\"Plain\" variant=\"primary\" items={items} />`;\n\nconst Layouts: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Layouts\" description=\"Default, outlined, rounded, sharp, and plain shapes.\">\n            <div style={{ display: 'flex', gap: 12, flexWrap: 'wrap', justifyContent: 'center' }}>\n                <SplitButton layout=\"default\" label=\"Default\" variant=\"primary\" items={items} />\n                <SplitButton layout=\"outlined\" label=\"Outlined\" variant=\"primary\" items={items} />\n                <SplitButton layout=\"rounded\" label=\"Rounded\" variant=\"primary\" items={items} />\n                <SplitButton layout=\"sharp\" label=\"Sharp\" variant=\"primary\" items={items} />\n                <SplitButton layout=\"plain\" label=\"Plain\" variant=\"primary\" items={items} />\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default Layouts;\n"
        },
        {
          "title": "Sizes",
          "code": "import React from 'react';\nimport { SplitButton } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst items = [\n    { label: 'Option A', onClick: () => {} },\n    { label: 'Option B', onClick: () => {} },\n];\n\nconst code = `<SplitButton size=\"xs\" label=\"XS\" items={items} />\n<SplitButton size=\"sm\" label=\"SM\" items={items} />\n<SplitButton size=\"md\" label=\"MD\" items={items} />\n<SplitButton size=\"lg\" label=\"LG\" items={items} />\n<SplitButton size=\"xl\" label=\"XL\" items={items} />`;\n\nconst Sizes: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Sizes\" description=\"Five preset sizes from xs through xl.\">\n            <div style={{ display: 'flex', gap: 12, flexWrap: 'wrap', alignItems: 'center', justifyContent: 'center' }}>\n                <SplitButton size=\"xs\" variant=\"primary\" label=\"XS\" items={items} />\n                <SplitButton size=\"sm\" variant=\"primary\" label=\"SM\" items={items} />\n                <SplitButton size=\"md\" variant=\"primary\" label=\"MD\" items={items} />\n                <SplitButton size=\"lg\" variant=\"primary\" label=\"LG\" items={items} />\n                <SplitButton size=\"xl\" variant=\"primary\" label=\"XL\" items={items} />\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default Sizes;\n"
        },
        {
          "title": "Variants",
          "code": "import React from 'react';\nimport { SplitButton } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst items = [\n    { label: 'Option A', onClick: () => {} },\n    { label: 'Option B', onClick: () => {} },\n    { label: 'Option C', onClick: () => {} },\n];\n\nconst code = `<SplitButton variant=\"default\" label=\"Default\" items={items} />\n<SplitButton variant=\"primary\" label=\"Primary\" items={items} />\n<SplitButton variant=\"success\" label=\"Success\" items={items} />\n<SplitButton variant=\"warning\" label=\"Warning\" items={items} />\n<SplitButton variant=\"danger\" label=\"Danger\" items={items} />\n<SplitButton variant=\"info\" label=\"Info\" items={items} />\n<SplitButton variant=\"secondary\" label=\"Secondary\" items={items} />`;\n\nconst Variants: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Variants\" description=\"All seven Button variants flow through both halves.\">\n            <div style={{ display: 'flex', gap: 12, flexWrap: 'wrap', justifyContent: 'center' }}>\n                <SplitButton variant=\"default\" label=\"Default\" items={items} />\n                <SplitButton variant=\"primary\" label=\"Primary\" items={items} />\n                <SplitButton variant=\"success\" label=\"Success\" items={items} />\n                <SplitButton variant=\"warning\" label=\"Warning\" items={items} />\n                <SplitButton variant=\"danger\" label=\"Danger\" items={items} />\n                <SplitButton variant=\"info\" label=\"Info\" items={items} />\n                <SplitButton variant=\"secondary\" label=\"Secondary\" items={items} />\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default Variants;\n"
        }
      ],
      "props": {
        "splitButtonProps": {
          "label": {
            "type": "string",
            "required": true,
            "description": "Primary action text"
          },
          "onClick": {
            "type": "(e: MouseEvent) => void | Promise<unknown>",
            "description": "Primary action handler (supports async loading state)"
          },
          "items": {
            "type": "Array<SplitButtonItem>",
            "required": true,
            "description": "Menu items: { label, icon?, onClick?, disabled?, danger?, divider?, shortcut? }"
          },
          "variant": {
            "type": "'success' | 'warning' | 'danger' | 'info' | 'default' | 'primary' | 'secondary'",
            "default": "'primary'",
            "description": "Color variant applied to both halves"
          },
          "layout": {
            "type": "'default' | 'outlined' | 'plain' | 'rounded' | 'sharp'",
            "default": "'default'",
            "description": "Shared button layout"
          },
          "size": {
            "type": "'xs' | 'sm' | 'md' | 'lg' | 'xl'",
            "default": "'md'",
            "description": "Shared button size"
          },
          "leftIcon": {
            "type": "IconComponent | ReactElement",
            "description": "Icon on the left side of the primary button"
          },
          "rightIcon": {
            "type": "IconComponent | ReactElement",
            "description": "Icon on the right side of the primary button"
          },
          "loading": {
            "type": "boolean",
            "default": "false",
            "description": "Show loading spinner on the primary button"
          },
          "disabled": {
            "type": "boolean",
            "default": "false",
            "description": "Disable both halves"
          },
          "menuPlacement": {
            "type": "'bottom-start' | 'bottom-end' | 'top-start' | 'top-end' | 'auto'",
            "default": "'bottom-end'",
            "description": "Preferred menu placement (auto-flips when out of viewport)"
          },
          "menuWidth": {
            "type": "'trigger' | 'auto' | number",
            "default": "'auto'",
            "description": "Menu width: 'trigger' matches the SplitButton, 'auto' fits content, or a px number"
          },
          "triggerIcon": {
            "type": "IconComponent | ReactElement",
            "description": "Icon used on the secondary trigger (default chevron-down)"
          },
          "ariaLabel": {
            "type": "string",
            "description": "Accessible label for the trigger (default: 'More {label} actions')"
          },
          "id": {
            "type": "string",
            "description": "HTML id attribute"
          },
          "className": {
            "type": "string",
            "description": "Additional CSS classes"
          }
        }
      },
      "storyDir": "split-button"
    },
    "Splitter": {
      "name": "Splitter",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "DefaultSizePct",
          "code": "import React from 'react';\nimport { Splitter, SplitterPanel } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<Splitter style={{ height: '200px' }}>\n  <SplitterPanel defaultSize=\"30%\">\n    <div className=\"p-4\">30% Panel</div>\n  </SplitterPanel>\n  <SplitterPanel>\n    <div className=\"p-4\">70% Panel</div>\n  </SplitterPanel>\n</Splitter>`;\n\nconst DefaultSizePct: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo title=\"defaultSize='30%' on first panel\">\n                <div className=\"h-48 w-full border border-gray-200 dark:border-white/10 rounded overflow-hidden\">\n                    <Splitter style={{ height: '100%' }}>\n                        <SplitterPanel defaultSize=\"30%\">\n                            <div className=\"h-full p-4\">\n                                <p className=\"font-semibold mb-1\">30% Panel</p>\n                                <p className=\"text-sm opacity-60\">Starts at 30% of container width.</p>\n                            </div>\n                        </SplitterPanel>\n                        <SplitterPanel>\n                            <div className=\"h-full p-4\">\n                                <p className=\"font-semibold mb-1\">70% Panel</p>\n                                <p className=\"text-sm opacity-60\">Fills the remaining 70%.</p>\n                            </div>\n                        </SplitterPanel>\n                    </Splitter>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default DefaultSizePct;\n"
        },
        {
          "title": "DefaultSizePx",
          "code": "import React from 'react';\nimport { Splitter, SplitterPanel } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<Splitter style={{ height: '200px' }}>\n  <SplitterPanel defaultSize=\"280px\">\n    <div className=\"p-4\">Sidebar — starts at 280px</div>\n  </SplitterPanel>\n  <SplitterPanel>\n    <div className=\"p-4\">Content Area</div>\n  </SplitterPanel>\n</Splitter>`;\n\nconst DefaultSizePx: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo title=\"defaultSize='280px' on first panel\">\n                <div className=\"h-48 w-full border border-gray-200 dark:border-white/10 rounded overflow-hidden\">\n                    <Splitter style={{ height: '100%' }}>\n                        <SplitterPanel defaultSize=\"280px\">\n                            <div className=\"h-full p-4\">\n                                <p className=\"font-semibold mb-1\">Sidebar</p>\n                                <p className=\"text-sm opacity-60\">Starts at 280 px wide.</p>\n                            </div>\n                        </SplitterPanel>\n                        <SplitterPanel>\n                            <div className=\"h-full p-4\">\n                                <p className=\"font-semibold mb-1\">Content Area</p>\n                                <p className=\"text-sm opacity-60\">Expands to fill the remaining width.</p>\n                            </div>\n                        </SplitterPanel>\n                    </Splitter>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default DefaultSizePx;\n"
        },
        {
          "title": "FixedPanel",
          "code": "import React from 'react';\nimport { Splitter, SplitterPanel } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<Splitter style={{ height: '200px' }}>\n  <SplitterPanel defaultSize=\"200px\" fixed>\n    <div className=\"p-4\">Fixed (200px) — cannot be resized</div>\n  </SplitterPanel>\n  <SplitterPanel>\n    <div className=\"p-4\">Fluid Panel</div>\n  </SplitterPanel>\n</Splitter>`;\n\nconst FixedPanel: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo title=\"fixed panel — cannot be resized\">\n                <div className=\"h-48 w-full border border-gray-200 dark:border-white/10 rounded overflow-hidden\">\n                    <Splitter style={{ height: '100%' }}>\n                        <SplitterPanel defaultSize=\"200px\" fixed>\n                            <div className=\"h-full p-4\">\n                                <p className=\"font-semibold mb-1\">Fixed (200px)</p>\n                                <p className=\"text-sm opacity-60\">This panel is locked and cannot be resized.</p>\n                            </div>\n                        </SplitterPanel>\n                        <SplitterPanel>\n                            <div className=\"h-full p-4\">\n                                <p className=\"font-semibold mb-1\">Fluid Panel</p>\n                                <p className=\"text-sm opacity-60\">Fills all remaining space.</p>\n                            </div>\n                        </SplitterPanel>\n                    </Splitter>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default FixedPanel;\n"
        },
        {
          "title": "GutterSize",
          "code": "import cn from 'classnames';\nimport React, { useState } from 'react';\nimport { Splitter, SplitterPanel } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\n\nconst code = `<Splitter gutterSize={10} style={{ height: '200px' }}>\n  <SplitterPanel>\n    <div className=\"p-4\">Left Panel</div>\n  </SplitterPanel>\n  <SplitterPanel>\n    <div className=\"p-4\">Right Panel</div>\n  </SplitterPanel>\n</Splitter>`;\n\nconst GutterSize: React.FC = () => {\n    const { isDark } = useStoryTheme();\n    const [gutterSize, setGutterSize] = useState(4);\n\n    return (\n        <>\n            <ComponentDemo title=\"gutterSize — drag the slider to change gutter thickness\">\n                <div className=\"flex items-center gap-4 mb-4\">\n                    <label className={cn('text-sm', { 'text-gray-400': isDark, 'text-gray-600': !isDark })}>\n                        gutterSize: {gutterSize}px\n                    </label>\n                    <input\n                        type=\"range\"\n                        min={2}\n                        max={20}\n                        value={gutterSize}\n                        onChange={(e) => setGutterSize(Number(e.target.value))}\n                        className=\"w-40\"\n                    />\n                </div>\n                <div className=\"h-48 w-full border border-gray-200 dark:border-white/10 rounded overflow-hidden\">\n                    <Splitter gutterSize={gutterSize} style={{ height: '100%' }}>\n                        <SplitterPanel>\n                            <div className=\"h-full p-4\">\n                                <p className=\"font-semibold mb-1\">Left Panel</p>\n                                <p className=\"text-sm opacity-60\">Adjust the slider above to change gutter thickness.</p>\n                            </div>\n                        </SplitterPanel>\n                        <SplitterPanel>\n                            <div className=\"h-full p-4\">\n                                <p className=\"font-semibold mb-1\">Right Panel</p>\n                            </div>\n                        </SplitterPanel>\n                    </Splitter>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default GutterSize;\n"
        },
        {
          "title": "HorizontalSplit",
          "code": "import React from 'react';\nimport { Splitter, SplitterPanel } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { Splitter, SplitterPanel } from 'fluxo-ui';\n\n<Splitter style={{ height: '200px' }}>\n  <SplitterPanel>\n    <div className=\"p-4\">Left Panel</div>\n  </SplitterPanel>\n  <SplitterPanel>\n    <div className=\"p-4\">Right Panel</div>\n  </SplitterPanel>\n</Splitter>`;\n\nconst HorizontalSplit: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo title=\"Horizontal Split\">\n                <div className=\"h-48 w-full border border-gray-200 dark:border-white/10 rounded overflow-hidden\">\n                    <Splitter style={{ height: '100%' }}>\n                        <SplitterPanel>\n                            <div className=\"h-full p-4\">\n                                <p className=\"font-semibold mb-1\">Left Panel</p>\n                                <p className=\"text-sm opacity-60\">Drag the gutter to resize horizontally.</p>\n                            </div>\n                        </SplitterPanel>\n                        <SplitterPanel>\n                            <div className=\"h-full p-4\">\n                                <p className=\"font-semibold mb-1\">Right Panel</p>\n                                <p className=\"text-sm opacity-60\">Fills the remaining space automatically.</p>\n                            </div>\n                        </SplitterPanel>\n                    </Splitter>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default HorizontalSplit;\n"
        },
        {
          "title": "KeyboardNavigation",
          "code": "import cn from 'classnames';\nimport React from 'react';\nimport { useStoryTheme } from '../../StoryThemeContext';\n\nconst keyboardRows = [\n    { key: '← / →', action: 'Move gutter left / right by 20px (horizontal layout)' },\n    { key: '↑ / ↓', action: 'Move gutter up / down by 20px (vertical layout)' },\n    { key: 'Tab', action: 'Focus the gutter from the page tab order' },\n];\n\nconst KeyboardNavigation: React.FC = () => {\n    const { isDark } = useStoryTheme();\n\n    return (\n        <div\n            className={cn('rounded-lg border overflow-hidden text-sm', {\n                'border-white/10 bg-white/4': isDark,\n                'border-gray-200 bg-white': !isDark,\n            })}\n        >\n            <table className=\"w-full\">\n                <thead>\n                    <tr\n                        className={cn('text-xs font-semibold uppercase tracking-wider', {\n                            'bg-white/6 text-gray-500': isDark,\n                            'bg-gray-50 text-gray-500': !isDark,\n                        })}\n                    >\n                        <th className=\"px-4 py-2 text-left\">Key</th>\n                        <th className=\"px-4 py-2 text-left\">Action</th>\n                    </tr>\n                </thead>\n                <tbody className={cn('divide-y', { 'divide-white/6': isDark, 'divide-gray-100': !isDark })}>\n                    {keyboardRows.map((row) => (\n                        <tr key={row.key} className={cn({ 'text-gray-300': isDark, 'text-gray-700': !isDark })}>\n                            <td className=\"px-4 py-2 font-mono font-medium\">{row.key}</td>\n                            <td className=\"px-4 py-2\">{row.action}</td>\n                        </tr>\n                    ))}\n                </tbody>\n            </table>\n        </div>\n    );\n};\n\nexport default KeyboardNavigation;\n"
        },
        {
          "title": "MinSize",
          "code": "import React from 'react';\nimport { Splitter, SplitterPanel } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<Splitter style={{ height: '200px' }}>\n  <SplitterPanel minSize=\"150px\">\n    <div className=\"p-4\">Min 150px</div>\n  </SplitterPanel>\n  <SplitterPanel minSize=\"20%\">\n    <div className=\"p-4\">Min 20%</div>\n  </SplitterPanel>\n</Splitter>`;\n\nconst MinSize: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo title=\"minSize='150px' and minSize='20%'\">\n                <div className=\"h-48 w-full border border-gray-200 dark:border-white/10 rounded overflow-hidden\">\n                    <Splitter style={{ height: '100%' }}>\n                        <SplitterPanel minSize=\"150px\">\n                            <div className=\"h-full p-4\">\n                                <p className=\"font-semibold mb-1\">Min 150px</p>\n                                <p className=\"text-sm opacity-60\">Cannot collapse below 150 px.</p>\n                            </div>\n                        </SplitterPanel>\n                        <SplitterPanel minSize=\"20%\">\n                            <div className=\"h-full p-4\">\n                                <p className=\"font-semibold mb-1\">Min 20%</p>\n                                <p className=\"text-sm opacity-60\">Cannot collapse below 20% of container width.</p>\n                            </div>\n                        </SplitterPanel>\n                    </Splitter>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default MinSize;\n"
        },
        {
          "title": "NestedSplitters",
          "code": "import React from 'react';\nimport { Splitter, SplitterPanel } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<Splitter style={{ height: '300px' }}>\n  <SplitterPanel defaultSize=\"200px\">\n    <div className=\"p-4\">Sidebar</div>\n  </SplitterPanel>\n  <SplitterPanel>\n    <Splitter layout=\"vertical\" style={{ height: '100%' }}>\n      <SplitterPanel>\n        <div className=\"p-4\">Editor</div>\n      </SplitterPanel>\n      <SplitterPanel defaultSize=\"100px\">\n        <div className=\"p-4\">Terminal</div>\n      </SplitterPanel>\n    </Splitter>\n  </SplitterPanel>\n</Splitter>`;\n\nconst NestedSplitters: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo title=\"IDE-style layout — sidebar + editor + terminal\">\n                <div className=\"h-64 w-full border border-gray-200 dark:border-white/10 rounded overflow-hidden\">\n                    <Splitter style={{ height: '100%' }}>\n                        <SplitterPanel defaultSize=\"200px\">\n                            <div className=\"h-full p-4\">\n                                <p className=\"font-semibold mb-1\">Sidebar</p>\n                                <p className=\"text-sm opacity-60\">File explorer</p>\n                            </div>\n                        </SplitterPanel>\n                        <SplitterPanel>\n                            <Splitter layout=\"vertical\" style={{ height: '100%' }}>\n                                <SplitterPanel>\n                                    <div className=\"h-full p-4\">\n                                        <p className=\"font-semibold mb-1\">Editor</p>\n                                        <p className=\"text-sm opacity-60\">Main editor area</p>\n                                    </div>\n                                </SplitterPanel>\n                                <SplitterPanel defaultSize=\"100px\">\n                                    <div className=\"h-full p-4\">\n                                        <p className=\"font-semibold mb-1\">Terminal</p>\n                                        <p className=\"text-sm opacity-60\">Output panel</p>\n                                    </div>\n                                </SplitterPanel>\n                            </Splitter>\n                        </SplitterPanel>\n                    </Splitter>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default NestedSplitters;\n"
        },
        {
          "title": "OnResizeEnd",
          "code": "import React, { useState } from 'react';\nimport { Splitter, SplitterPanel } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `const [savedSize, setSavedSize] = useState<number | null>(null);\n\n<Splitter\n  style={{ height: '200px' }}\n  onResizeEnd={(size) => {\n    setSavedSize(size);\n    localStorage.setItem('splitter-size', String(size));\n  }}\n>\n  <SplitterPanel>\n    <div className=\"p-4\">Panel A</div>\n  </SplitterPanel>\n  <SplitterPanel>\n    <div className=\"p-4\">Panel B</div>\n  </SplitterPanel>\n</Splitter>`;\n\nconst OnResizeEnd: React.FC = () => {\n    const [resizeLog, setResizeLog] = useState<number | null>(null);\n\n    return (\n        <>\n            <ComponentDemo title=\"onResizeEnd — fires when drag ends\">\n                <div className=\"h-48 w-full border border-gray-200 dark:border-white/10 rounded overflow-hidden\">\n                    <Splitter style={{ height: '100%' }} onResizeEnd={(size) => setResizeLog(Math.round(size))}>\n                        <SplitterPanel>\n                            <div className=\"h-full p-4\">\n                                <p className=\"font-semibold mb-1\">Drag me</p>\n                                <p className=\"text-sm opacity-60\">Release the gutter to fire the callback.</p>\n                            </div>\n                        </SplitterPanel>\n                        <SplitterPanel>\n                            <div className=\"h-full p-4\">\n                                <p className=\"font-semibold mb-1\">Right Panel</p>\n                                <p className=\"text-sm opacity-60\">\n                                    {resizeLog !== null\n                                        ? `onResizeEnd → first panel: ${resizeLog}px`\n                                        : 'Drag and release to see the callback value.'}\n                                </p>\n                            </div>\n                        </SplitterPanel>\n                    </Splitter>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default OnResizeEnd;\n"
        },
        {
          "title": "PersistingLayout",
          "code": "import React from 'react';\nimport { CodeBlock } from '../../CodeBlock';\n\nconst code = `function PersistentSplitter() {\n  const storageKey = 'my-splitter-size';\n\n  const savedSize = (() => {\n    const v = localStorage.getItem(storageKey);\n    return v ? \\`\\${v}px\\` : '300px';\n  })();\n\n  return (\n    <Splitter\n      style={{ height: '400px' }}\n      onResizeEnd={(size) => {\n        localStorage.setItem(storageKey, String(Math.round(size)));\n      }}\n    >\n      <SplitterPanel defaultSize={savedSize} minSize=\"100px\">\n        <div className=\"p-4\">Sidebar — size restored on reload</div>\n      </SplitterPanel>\n      <SplitterPanel minSize=\"200px\">\n        <div className=\"p-4\">Main content</div>\n      </SplitterPanel>\n    </Splitter>\n  );\n}`;\n\nconst PersistingLayout: React.FC = () => {\n    return (\n        <div className=\"mt-4\">\n            <CodeBlock code={code} />\n        </div>\n    );\n};\n\nexport default PersistingLayout;\n"
        },
        {
          "title": "Responsive",
          "code": "import React, { useState } from 'react';\nimport { Button, Slider, Splitter, SplitterPanel, TextInput } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `const [collapsed, setCollapsed] = useState(false);\n\n<Splitter\n  style={{ height: '100%' }}\n  responsive={520}\n  onCollapseChange={setCollapsed}\n>\n  <SplitterPanel defaultSize=\"40%\" minSize=\"160px\">\n    <div className=\"p-4\">Filters</div>\n  </SplitterPanel>\n  <SplitterPanel>\n    <div className=\"p-4\">Results</div>\n  </SplitterPanel>\n</Splitter>`;\n\nconst RESPONSIVE_THRESHOLD = 520;\n\nconst Responsive: React.FC = () => {\n    const [containerWidth, setContainerWidth] = useState(760);\n    const [collapsed, setCollapsed] = useState(false);\n    const [count, setCount] = useState(0);\n    const [note, setNote] = useState('');\n\n    return (\n        <>\n            <ComponentDemo title=\"Responsive collapse — horizontal turns into a vertical stack\">\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16 }}>\n                    <div\n                        style={{\n                            padding: '12px 16px',\n                            background: 'var(--eui-bg-subtle)',\n                            border: '1px solid var(--eui-border-subtle)',\n                            borderRadius: 6,\n                            display: 'flex',\n                            flexDirection: 'column',\n                            gap: 8,\n                        }}\n                    >\n                        <label htmlFor=\"splitter-responsive-width\" style={{ color: 'var(--eui-text)', fontWeight: 600, fontSize: 14 }}>\n                            Drag to change the splitter's container width\n                        </label>\n                        <Slider\n                            value={containerWidth}\n                            min={300}\n                            max={800}\n                            step={10}\n                            ariaLabel=\"Splitter container width\"\n                            valueFormat={(v) => `${v}px`}\n                            showValue\n                            onChange={(v) => setContainerWidth(Array.isArray(v) ? v[0] : v)}\n                        />\n                        <p style={{ color: 'var(--eui-text-muted)', fontSize: 13, margin: 0 }}>\n                            Container: <strong>{containerWidth}px</strong> · Threshold: <strong>{RESPONSIVE_THRESHOLD}px</strong> · Layout:{' '}\n                            <strong style={{ color: collapsed ? 'var(--eui-primary)' : 'var(--eui-text)' }}>\n                                {collapsed ? 'vertical (collapsed)' : 'horizontal'}\n                            </strong>\n                        </p>\n                    </div>\n\n                    <div\n                        style={{\n                            width: containerWidth,\n                            maxWidth: '100%',\n                            height: 260,\n                            border: '1px solid var(--eui-border)',\n                            borderRadius: 8,\n                            overflow: 'hidden',\n                            transition: 'width 0.2s ease',\n                        }}\n                    >\n                        <Splitter style={{ height: '100%' }} responsive={RESPONSIVE_THRESHOLD} onCollapseChange={setCollapsed}>\n                            <SplitterPanel defaultSize=\"40%\" minSize=\"160px\">\n                                <div style={{ height: '100%', padding: 16, display: 'flex', flexDirection: 'column', gap: 10 }}>\n                                    <p style={{ fontWeight: 600, color: 'var(--eui-text)', margin: 0 }}>Filters</p>\n                                    <p style={{ fontSize: 13, color: 'var(--eui-text-muted)', margin: 0 }}>\n                                        Click to change state, then narrow the width past {RESPONSIVE_THRESHOLD}px. The count survives the\n                                        collapse — panels are never unmounted.\n                                    </p>\n                                    <Button size=\"sm\" onClick={() => setCount((c) => c + 1)}>\n                                        Clicked {count} {count === 1 ? 'time' : 'times'}\n                                    </Button>\n                                </div>\n                            </SplitterPanel>\n                            <SplitterPanel>\n                                <div style={{ height: '100%', padding: 16, display: 'flex', flexDirection: 'column', gap: 10 }}>\n                                    <p style={{ fontWeight: 600, color: 'var(--eui-text)', margin: 0 }}>Results</p>\n                                    <label\n                                        htmlFor=\"splitter-responsive-note\"\n                                        style={{ fontSize: 13, color: 'var(--eui-text-muted)' }}\n                                    >\n                                        Type something\n                                    </label>\n                                    <TextInput\n                                        id=\"splitter-responsive-note\"\n                                        value={note}\n                                        placeholder=\"Your text stays put when it stacks\"\n                                        onChange={(e) => setNote(e.value)}\n                                    />\n                                </div>\n                            </SplitterPanel>\n                        </Splitter>\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default Responsive;\n"
        },
        {
          "title": "VerticalSplit",
          "code": "import React from 'react';\nimport { Splitter, SplitterPanel } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<Splitter layout=\"vertical\" style={{ height: '300px' }}>\n  <SplitterPanel>\n    <div className=\"p-4\">Top Panel</div>\n  </SplitterPanel>\n  <SplitterPanel>\n    <div className=\"p-4\">Bottom Panel</div>\n  </SplitterPanel>\n</Splitter>`;\n\nconst VerticalSplit: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo title=\"Vertical Split\">\n                <div className=\"h-64 w-full border border-gray-200 dark:border-white/10 rounded overflow-hidden\">\n                    <Splitter layout=\"vertical\" style={{ height: '100%' }}>\n                        <SplitterPanel>\n                            <div className=\"h-full p-4\">\n                                <p className=\"font-semibold mb-1\">Top Panel</p>\n                                <p className=\"text-sm opacity-60\">Drag the horizontal gutter to resize.</p>\n                            </div>\n                        </SplitterPanel>\n                        <SplitterPanel>\n                            <div className=\"h-full p-4\">\n                                <p className=\"font-semibold mb-1\">Bottom Panel</p>\n                                <p className=\"text-sm opacity-60\">Fills the remaining vertical space.</p>\n                            </div>\n                        </SplitterPanel>\n                    </Splitter>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default VerticalSplit;\n"
        }
      ],
      "props": {
        "splitterProps": {
          "layout": {
            "type": "'horizontal' | 'vertical'",
            "default": "'horizontal'",
            "description": "Direction in which panels are laid out. 'horizontal' places panels side by side; 'vertical' stacks them."
          },
          "gutterSize": {
            "type": "number",
            "default": "4",
            "description": "Width (or height) in pixels of the drag handle bar between panels."
          },
          "onResizeEnd": {
            "type": "(firstPanelSize: number) => void",
            "description": "Called after the user finishes a drag with the new first-panel size in pixels."
          },
          "responsive": {
            "type": "number",
            "description": "Container width in px (measured on the splitter itself, not the viewport) below which a horizontal splitter collapses from side-by-side panels into a stacked layout. Applies to layout=\"horizontal\" only — a vertical splitter is already stacked and ignores it. The collapse only flips layout styles and swaps the draggable gutter for a static divider, so panels are never unmounted and child state is preserved. Omit to disable."
          },
          "collapsedLayout": {
            "type": "'horizontal' | 'vertical'",
            "default": "'vertical'",
            "description": "Direction panels stack in once collapsed (only used with responsive)."
          },
          "onCollapseChange": {
            "type": "(collapsed: boolean) => void",
            "description": "Called when the splitter crosses the responsive threshold, with the new collapsed state."
          },
          "className": {
            "type": "string",
            "description": "Additional CSS classes for the outer container."
          },
          "style": {
            "type": "React.CSSProperties",
            "description": "Inline styles for the outer container."
          },
          "children": {
            "type": "React.ReactNode",
            "required": true,
            "description": "Exactly two SplitterPanel children are required."
          }
        },
        "splitterPanelProps": {
          "defaultSize": {
            "type": "string",
            "description": "Initial size of the panel. Accepts px (e.g. '300px') or % (e.g. '40%'). Only one panel should set this — the sibling fills the remaining space."
          },
          "minSize": {
            "type": "string",
            "default": "'0px'",
            "description": "Minimum size of the panel. Accepts px or %. Prevents the panel from being resized below this threshold."
          },
          "fixed": {
            "type": "boolean",
            "default": "false",
            "description": "When true, the panel cannot be resized by the user."
          },
          "className": {
            "type": "string",
            "description": "Additional CSS classes for the panel container."
          },
          "style": {
            "type": "React.CSSProperties",
            "description": "Inline styles for the panel container."
          },
          "children": {
            "type": "React.ReactNode",
            "description": "Content to render inside the panel."
          }
        }
      },
      "storyDir": "splitter"
    },
    "StepDots": {
      "name": "StepDots",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React, { useState } from 'react';\nimport { Button, StepDots } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { StepDots } from 'fluxo-ui';\n\n<StepDots count={4} activeIndex={index} />`;\n\nconst BasicUsage: React.FC = () => {\n    const [idx, setIdx] = useState(1);\n    return (\n        <>\n            <ComponentDemo title=\"Simple progress dots\" description=\"Tiny indicator showing position in an onboarding or carousel. Tap the buttons to step through.\">\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 16 }}>\n                    <StepDots count={4} activeIndex={idx} />\n                    <div style={{ display: 'flex', gap: 8 }}>\n                        <Button label=\"Prev\" variant=\"secondary\" disabled={idx === 0} onClick={() => setIdx((n) => Math.max(0, n - 1))} />\n                        <Button label=\"Next\" disabled={idx === 3} onClick={() => setIdx((n) => Math.min(3, n + 1))} />\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\"><CodeBlock code={code} language=\"tsx\" /></div>\n        </>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "Interactive",
          "code": "import React, { useState } from 'react';\nimport { StepDots } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<StepDots count={5} activeIndex={i} onChange={setI} interactive />`;\n\nconst Interactive: React.FC = () => {\n    const [idx, setIdx] = useState(0);\n    return (\n        <>\n            <ComponentDemo title=\"Interactive\" description=\"Add interactive to make dots focusable and clickable. Arrow keys navigate the active dot.\">\n                <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 12, width: '100%' }}>\n                    <StepDots count={5} activeIndex={idx} onChange={setIdx} interactive />\n                    <div style={{ fontSize: 13, color: 'var(--eui-text-muted)' }}>Current: step {idx + 1} of 5</div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\"><CodeBlock code={code} language=\"tsx\" /></div>\n        </>\n    );\n};\n\nexport default Interactive;\n"
        },
        {
          "title": "Sizes",
          "code": "import React from 'react';\nimport { StepDots } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<StepDots size=\"sm\" count={5} activeIndex={2} />\n<StepDots size=\"md\" count={5} activeIndex={2} />\n<StepDots size=\"lg\" count={5} activeIndex={2} />`;\n\nconst Sizes: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Three sizes\" description=\"Default sizes scale all variants. 'sm' fits inline with text, 'lg' is suitable for hero carousels.\">\n            <div style={{ display: 'flex', flexDirection: 'column', gap: 16, alignItems: 'center', width: '100%' }}>\n                <StepDots size=\"sm\" count={5} activeIndex={2} />\n                <StepDots size=\"md\" count={5} activeIndex={2} />\n                <StepDots size=\"lg\" count={5} activeIndex={2} />\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\"><CodeBlock code={code} language=\"tsx\" /></div>\n    </>\n);\n\nexport default Sizes;\n"
        },
        {
          "title": "Variants",
          "code": "import React from 'react';\nimport { StepDots } from '../../../components';\nimport type { StepDotsVariant } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst variants: { variant: StepDotsVariant; title: string; description: string }[] = [\n    { variant: 'dot', title: 'Dot (default)', description: 'Active dot stretches into a pill.' },\n    { variant: 'bar', title: 'Bar', description: 'Horizontal bars — works well with edge-to-edge carousels.' },\n    { variant: 'pill', title: 'Pill', description: 'All completed/active dots fill — minimal animation.' },\n    { variant: 'numbered', title: 'Numbered', description: 'Each step shows its number — for guided wizards.' },\n];\n\nconst code = `<StepDots variant=\"bar\" count={5} activeIndex={2} />`;\n\nconst Variants: React.FC = () => (\n    <>\n        {variants.map(({ variant, title, description }) => (\n            <ComponentDemo key={variant} title={title} description={description} className={variant === 'dot' ? '' : 'mt-4'}>\n                <div style={{ display: 'flex', justifyContent: 'center', width: '100%' }}>\n                    <StepDots variant={variant} count={5} activeIndex={2} />\n                </div>\n            </ComponentDemo>\n        ))}\n        <div className=\"mt-4\"><CodeBlock code={code} language=\"tsx\" /></div>\n    </>\n);\n\nexport default Variants;\n"
        }
      ],
      "props": {
        "stepDotsProps": {
          "count": {
            "type": "number",
            "required": true,
            "description": "Total number of steps."
          },
          "activeIndex": {
            "type": "number",
            "required": true,
            "description": "Zero-based index of the currently active step."
          },
          "onChange": {
            "type": "(index: number) => void",
            "description": "Called when the user activates a dot (only when interactive=true)."
          },
          "variant": {
            "type": "'dot' | 'bar' | 'pill' | 'numbered'",
            "default": "'dot'",
            "description": "Visual style. 'dot' grows the active dot into a pill, 'bar' uses horizontal bars, 'pill' fills completed/active dots, 'numbered' shows step numbers."
          },
          "size": {
            "type": "'sm' | 'md' | 'lg'",
            "default": "'md'",
            "description": "Size of the dots."
          },
          "color": {
            "type": "string",
            "description": "Override color for the active dot."
          },
          "inactiveColor": {
            "type": "string",
            "description": "Override color for inactive dots."
          },
          "interactive": {
            "type": "boolean",
            "default": "false",
            "description": "Allow keyboard/click activation of dots."
          },
          "showLabels": {
            "type": "boolean",
            "default": "false",
            "description": "Add visually-hidden labels for screen readers (always on for numbered variant via aria-label)."
          },
          "labelFormatter": {
            "type": "(index: number, total: number) => string",
            "description": "Custom label formatter for each dot's accessible name."
          },
          "className": {
            "type": "string",
            "description": "Additional CSS class for the wrapper."
          },
          "ariaLabel": {
            "type": "string",
            "default": "'Step progress'",
            "description": "Accessible name for the tablist."
          }
        }
      },
      "storyDir": "step-dots"
    },
    "StickyScroll": {
      "name": "StickyScroll",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React, { useEffect, useRef, useState } from 'react';\nimport { Button, StickyScroll } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { StickyScroll } from 'fluxo-ui';\n\n<StickyScroll maxHeight={320}>\n    {messages.map((m) => (\n        <div key={m.id}>{m.text}</div>\n    ))}\n</StickyScroll>`;\n\ninterface FeedEntry {\n    id: number;\n    text: string;\n}\n\nconst lines = [\n    'Agent connected to the bound tab.',\n    'Reading page info — title, URL, ready state.',\n    'Clicking the \"New invoice\" button.',\n    'Filling customer name with \"Acme Corp\".',\n    'Selecting currency: USD.',\n    'Waiting for the line-items table to render.',\n    'Inspecting the computed total.',\n    'Capturing a screenshot for the step.',\n    'Validating the success toast appeared.',\n];\n\nconst BasicUsage: React.FC = () => {\n    const [entries, setEntries] = useState<FeedEntry[]>(() =>\n        lines.slice(0, 4).map((text, id) => ({ id, text })),\n    );\n    const counter = useRef<number>(4);\n\n    useEffect(() => {\n        const timer = setInterval(() => {\n            setEntries((prev) => {\n                const next = lines[counter.current % lines.length];\n                const entry: FeedEntry = { id: counter.current, text: next };\n                counter.current += 1;\n                return [...prev, entry];\n            });\n        }, 1800);\n        return () => clearInterval(timer);\n    }, []);\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Live activity feed\"\n                description=\"New rows stream in every 1.8s. While you are at the bottom the view auto-follows. Scroll up to read an older row and it stays put — a 'jump to latest' button appears so you can re-pin.\"\n            >\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 12 }}>\n                    <StickyScroll\n                        maxHeight={300}\n                        role=\"log\"\n                        ariaLabel=\"Activity feed\"\n                        className=\"eui-demo-sticky\"\n                    >\n                        {entries.map((entry) => (\n                            <div\n                                key={entry.id}\n                                style={{\n                                    padding: '10px 14px',\n                                    borderBottom: '1px solid var(--eui-border-subtle)',\n                                    color: 'var(--eui-text)',\n                                    fontSize: 13,\n                                }}\n                            >\n                                <span style={{ color: 'var(--eui-text-muted)', marginRight: 8 }}>\n                                    #{entry.id + 1}\n                                </span>\n                                {entry.text}\n                            </div>\n                        ))}\n                    </StickyScroll>\n                    <div\n                        style={{\n                            display: 'flex',\n                            gap: 8,\n                            padding: '10px 14px',\n                            background: 'var(--eui-bg-subtle)',\n                            border: '1px solid var(--eui-border-subtle)',\n                            borderRadius: 6,\n                        }}\n                    >\n                        <Button\n                            size=\"sm\"\n                            label=\"Add row\"\n                            onClick={() =>\n                                setEntries((prev) => {\n                                    const next = lines[counter.current % lines.length];\n                                    const entry: FeedEntry = { id: counter.current, text: next };\n                                    counter.current += 1;\n                                    return [...prev, entry];\n                                })\n                            }\n                        />\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "Imperative",
          "code": "import React, { useRef, useState } from 'react';\nimport { Button, StickyScroll } from '../../../components';\nimport type { StickyScrollHandle } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `const ref = useRef<StickyScrollHandle>(null);\n\n<StickyScroll ref={ref} maxHeight={300} onPinnedChange={setPinned}>\n    {rows}\n</StickyScroll>\n\n<Button label=\"Scroll to bottom\" onClick={() => ref.current?.scrollToBottom()} />`;\n\nconst Imperative: React.FC = () => {\n    const ref = useRef<StickyScrollHandle>(null);\n    const [rows, setRows] = useState<number[]>(() => Array.from({ length: 20 }, (_, i) => i));\n    const [pinned, setPinned] = useState<boolean>(true);\n    const counter = useRef<number>(20);\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Imperative handle & pinned state\"\n                description=\"Call scrollToBottom() via a ref, and observe pinned state through onPinnedChange. Useful for a custom 'send' button that always re-pins.\"\n            >\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 12 }}>\n                    <StickyScroll ref={ref} maxHeight={300} onPinnedChange={setPinned} ariaLabel=\"Items\">\n                        {rows.map((row) => (\n                            <div\n                                key={row}\n                                style={{\n                                    padding: '10px 14px',\n                                    borderBottom: '1px solid var(--eui-border-subtle)',\n                                    color: 'var(--eui-text)',\n                                    fontSize: 13,\n                                }}\n                            >\n                                Item {row + 1}\n                            </div>\n                        ))}\n                    </StickyScroll>\n                    <div\n                        style={{\n                            display: 'flex',\n                            flexWrap: 'wrap',\n                            alignItems: 'center',\n                            gap: 8,\n                            padding: '10px 14px',\n                            background: 'var(--eui-bg-subtle)',\n                            border: '1px solid var(--eui-border-subtle)',\n                            borderRadius: 6,\n                        }}\n                    >\n                        <Button\n                            size=\"sm\"\n                            label=\"Add item\"\n                            onClick={() =>\n                                setRows((prev) => {\n                                    const next = counter.current;\n                                    counter.current += 1;\n                                    return [...prev, next];\n                                })\n                            }\n                        />\n                        <Button size=\"sm\" layout=\"outlined\" label=\"Scroll to bottom\" onClick={() => ref.current?.scrollToBottom()} />\n                        <span style={{ color: 'var(--eui-text-muted)', fontSize: 13 }}>\n                            pinned: <strong style={{ color: 'var(--eui-text)' }}>{String(pinned)}</strong>\n                        </span>\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default Imperative;\n"
        },
        {
          "title": "WithLabel",
          "code": "import React, { useEffect, useRef, useState } from 'react';\nimport { StickyScroll } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<StickyScroll maxHeight={300} jumpButtonLabel=\"Jump to latest\">\n    {rows}\n</StickyScroll>`;\n\nconst WithLabel: React.FC = () => {\n    const [rows, setRows] = useState<number[]>(() => Array.from({ length: 6 }, (_, i) => i));\n    const counter = useRef<number>(6);\n\n    useEffect(() => {\n        const timer = setInterval(() => {\n            setRows((prev) => {\n                const next = counter.current;\n                counter.current += 1;\n                return [...prev, next];\n            });\n        }, 2200);\n        return () => clearInterval(timer);\n    }, []);\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Labelled jump button\"\n                description=\"Pass jumpButtonLabel to render a pill with text instead of the icon-only chevron. It only shows while the user has scrolled away from the bottom.\"\n            >\n                <div style={{ width: '100%' }}>\n                    <StickyScroll maxHeight={300} jumpButtonLabel=\"Jump to latest\" ariaLabel=\"Build log\">\n                        {rows.map((row) => (\n                            <div\n                                key={row}\n                                style={{\n                                    padding: '10px 14px',\n                                    borderBottom: '1px solid var(--eui-border-subtle)',\n                                    color: 'var(--eui-text)',\n                                    fontSize: 13,\n                                    fontFamily: 'var(--eui-font-mono, ui-monospace, monospace)',\n                                }}\n                            >\n                                line {row + 1}: compiled module successfully\n                            </div>\n                        ))}\n                    </StickyScroll>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default WithLabel;\n"
        }
      ],
      "props": {
        "stickyScrollProps": {
          "children": {
            "type": "ReactNode",
            "required": true,
            "description": "Scrollable content. New items appended at the end trigger auto-scroll when pinned"
          },
          "threshold": {
            "type": "number",
            "default": "48",
            "description": "Distance in px from the bottom within which the view is considered pinned"
          },
          "initialPinned": {
            "type": "boolean",
            "default": "true",
            "description": "Start scrolled to the bottom and pinned on mount"
          },
          "behavior": {
            "type": "'smooth' | 'auto'",
            "default": "'smooth'",
            "description": "Scroll behavior for the jump button; auto-falls back under prefers-reduced-motion"
          },
          "showJumpButton": {
            "type": "boolean",
            "default": "true",
            "description": "Show a 'jump to latest' button while the user is scrolled up"
          },
          "jumpButtonLabel": {
            "type": "string",
            "description": "Optional visible text on the jump button (icon-only when omitted)"
          },
          "maxHeight": {
            "type": "number | string",
            "description": "Max height of the scroll viewport (number is px)"
          },
          "height": {
            "type": "number | string",
            "description": "Fixed height of the scroll viewport (number is px)"
          },
          "onPinnedChange": {
            "type": "(pinned: boolean) => void",
            "description": "Fires when the pinned-to-bottom state changes"
          },
          "className": {
            "type": "string",
            "description": "Additional CSS classes on the outer wrapper"
          },
          "contentClassName": {
            "type": "string",
            "description": "Additional CSS classes on the inner content element"
          },
          "id": {
            "type": "string",
            "description": "HTML id attribute on the scroll viewport"
          },
          "ariaLabel": {
            "type": "string",
            "description": "Accessible label for the scroll viewport"
          },
          "role": {
            "type": "string",
            "description": "ARIA role for the scroll viewport (e.g. 'log' for live activity feeds)"
          }
        }
      },
      "storyDir": "sticky-scroll"
    },
    "SwipeableListItem": {
      "name": "SwipeableListItem",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React, { useState } from 'react';\nimport { SwipeableListItem } from '../../../components';\nimport { TrashIcon, ArchivedIcon, StarIcon } from '../../../assets/icons';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { SwipeableListItem } from 'fluxo-ui';\n\n<SwipeableListItem\n    rightActions={[\n        { label: 'Archive', icon: <ArchivedIcon />, color: 'warning', onTrigger: archive },\n        { label: 'Delete', icon: <TrashIcon />, color: 'danger', onTrigger: remove },\n    ]}\n    leftActions={[\n        { label: 'Star', icon: <StarIcon />, color: 'primary', onTrigger: star },\n    ]}\n>\n    <div>Subject line — preview text…</div>\n</SwipeableListItem>`;\n\ninterface Row { id: number; subject: string; preview: string; }\n\nconst initial: Row[] = [\n    { id: 1, subject: 'Build status', preview: 'main is green — all checks passed.' },\n    { id: 2, subject: 'Welcome aboard', preview: 'Onboarding kit attached.' },\n    { id: 3, subject: 'Standup notes', preview: 'Three items for tomorrow.' },\n    { id: 4, subject: 'New comment', preview: '@alex replied to your card.' },\n];\n\nconst noteBox: React.CSSProperties = {\n    padding: '10px 14px',\n    background: 'var(--eui-bg-subtle)',\n    border: '1px solid var(--eui-border-subtle)',\n    borderRadius: 6,\n    fontSize: 12,\n    color: 'var(--eui-text-muted)',\n};\n\nconst BasicUsage: React.FC = () => {\n    const [rows, setRows] = useState<Row[]>(initial);\n    const [last, setLast] = useState<string | null>(null);\n\n    const remove = (id: number) => {\n        setRows((r) => r.filter((row) => row.id !== id));\n        setLast(`Deleted #${id}`);\n    };\n    const archive = (id: number) => {\n        setRows((r) => r.filter((row) => row.id !== id));\n        setLast(`Archived #${id}`);\n    };\n    const star = (id: number) => setLast(`Starred #${id}`);\n\n    return (\n        <>\n            <ComponentDemo title=\"Swipe to reveal actions\" description=\"Drag a row left to reveal Archive + Delete, drag right to reveal Star. Tap a revealed action to trigger it.\">\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 16 }}>\n                    <div style={{\n                        width: '100%',\n                        maxWidth: 480,\n                        border: '1px solid var(--eui-border-subtle)',\n                        borderRadius: 8,\n                        overflow: 'hidden',\n                        background: 'var(--eui-bg)',\n                    }}>\n                        {rows.length === 0 && (\n                            <div style={{ padding: 24, textAlign: 'center', color: 'var(--eui-text-muted)' }}>\n                                Inbox cleared. Reload the page to reset.\n                            </div>\n                        )}\n                        {rows.map((row, idx) => (\n                            <SwipeableListItem\n                                key={row.id}\n                                leftActions={[\n                                    { label: 'Star', icon: <StarIcon />, color: 'primary', onTrigger: () => star(row.id) },\n                                ]}\n                                rightActions={[\n                                    { label: 'Archive', icon: <ArchivedIcon />, color: 'warning', onTrigger: () => archive(row.id) },\n                                    { label: 'Delete', icon: <TrashIcon />, color: 'danger', onTrigger: () => remove(row.id), fullSwipe: true },\n                                ]}\n                                className={idx > 0 ? 'eui-divided-row' : undefined}\n                            >\n                                <div>\n                                    <div style={{ fontWeight: 600, color: 'var(--eui-text)' }}>{row.subject}</div>\n                                    <div style={{ fontSize: 13, color: 'var(--eui-text-muted)', marginTop: 2 }}>{row.preview}</div>\n                                </div>\n                            </SwipeableListItem>\n                        ))}\n                    </div>\n                    <div style={noteBox}>Last action: <strong style={{ color: 'var(--eui-text)' }}>{last ?? '—'}</strong></div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\"><CodeBlock code={code} language=\"tsx\" /></div>\n        </>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "FullSwipe",
          "code": "import React, { useState } from 'react';\nimport { SwipeableListItem } from '../../../components';\nimport { TrashIcon } from '../../../assets/icons';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<SwipeableListItem\n    rightActions={[\n        { label: 'Delete', icon: <TrashIcon />, color: 'danger', fullSwipe: true, onTrigger: remove },\n    ]}\n    fullSwipeThreshold={0.7}\n>\n    {/* row content */}\n</SwipeableListItem>`;\n\nconst FullSwipe: React.FC = () => {\n    const [rows, setRows] = useState<number[]>([1, 2, 3, 4, 5]);\n    return (\n        <>\n            <ComponentDemo title=\"Full-swipe to trigger\" description=\"Set fullSwipe on an action and swipe past 70% — the action fires automatically without a tap.\">\n                <div style={{ width: '100%', maxWidth: 480, border: '1px solid var(--eui-border-subtle)', borderRadius: 8, overflow: 'hidden' }}>\n                    {rows.map((id) => (\n                        <SwipeableListItem\n                            key={id}\n                            fullSwipeThreshold={0.7}\n                            rightActions={[{\n                                label: 'Delete',\n                                icon: <TrashIcon />,\n                                color: 'danger',\n                                fullSwipe: true,\n                                onTrigger: () => setRows((r) => r.filter((v) => v !== id)),\n                            }]}\n                        >\n                            <div style={{ color: 'var(--eui-text)' }}>Item #{id} — full-swipe left to delete</div>\n                        </SwipeableListItem>\n                    ))}\n                    {rows.length === 0 && (\n                        <div style={{ padding: 24, textAlign: 'center', color: 'var(--eui-text-muted)' }}>All rows cleared — reload to reset.</div>\n                    )}\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\"><CodeBlock code={code} language=\"tsx\" /></div>\n        </>\n    );\n};\n\nexport default FullSwipe;\n"
        },
        {
          "title": "Variants",
          "code": "import React from 'react';\nimport { SwipeableListItem } from '../../../components';\nimport { TrashIcon, EditIcon, StarIcon } from '../../../assets/icons';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<SwipeableListItem variant=\"card\" rightActions={...}>\n    {/* row body */}\n</SwipeableListItem>`;\n\nconst Variants: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Inline variant (default)\" description=\"Flush list rows — best for traditional list views.\">\n            <div style={{ width: '100%', maxWidth: 480, border: '1px solid var(--eui-border-subtle)', borderRadius: 8, overflow: 'hidden' }}>\n                <SwipeableListItem rightActions={[{ label: 'Delete', icon: <TrashIcon />, color: 'danger' }]}>\n                    <div style={{ color: 'var(--eui-text)' }}>Inline row — swipe left to reveal delete</div>\n                </SwipeableListItem>\n                <SwipeableListItem rightActions={[{ label: 'Edit', icon: <EditIcon />, color: 'primary' }]}>\n                    <div style={{ color: 'var(--eui-text)' }}>Another inline row</div>\n                </SwipeableListItem>\n            </div>\n        </ComponentDemo>\n\n        <ComponentDemo title=\"Card variant\" description=\"Each row is a rounded card with a subtle border — works well for tile-like list patterns.\" className=\"mt-4\">\n            <div style={{ width: '100%', maxWidth: 480 }}>\n                <SwipeableListItem variant=\"card\" leftActions={[{ label: 'Star', icon: <StarIcon />, color: 'primary' }]} rightActions={[{ label: 'Delete', icon: <TrashIcon />, color: 'danger' }]}>\n                    <div style={{ color: 'var(--eui-text)' }}>Card-style row — swipe in either direction</div>\n                </SwipeableListItem>\n                <SwipeableListItem variant=\"card\" rightActions={[{ label: 'Edit', icon: <EditIcon />, color: 'primary' }]}>\n                    <div style={{ color: 'var(--eui-text)' }}>Another card row</div>\n                </SwipeableListItem>\n            </div>\n        </ComponentDemo>\n\n        <ComponentDemo title=\"Compact variant\" description=\"Tighter padding and smaller text for dense lists.\" className=\"mt-4\">\n            <div style={{ width: '100%', maxWidth: 480, border: '1px solid var(--eui-border-subtle)', borderRadius: 8, overflow: 'hidden' }}>\n                <SwipeableListItem variant=\"compact\" rightActions={[{ label: 'Delete', icon: <TrashIcon />, color: 'danger' }]}>\n                    <div style={{ color: 'var(--eui-text)' }}>Compact row</div>\n                </SwipeableListItem>\n                <SwipeableListItem variant=\"compact\" rightActions={[{ label: 'Delete', icon: <TrashIcon />, color: 'danger' }]}>\n                    <div style={{ color: 'var(--eui-text)' }}>Another compact row</div>\n                </SwipeableListItem>\n            </div>\n        </ComponentDemo>\n\n        <div className=\"mt-4\"><CodeBlock code={code} language=\"tsx\" /></div>\n    </>\n);\n\nexport default Variants;\n"
        }
      ],
      "props": {
        "swipeableListItemProps": {
          "children": {
            "type": "ReactNode",
            "required": true,
            "description": "Main row content that is revealed/translated when the user swipes."
          },
          "leftActions": {
            "type": "SwipeableAction[]",
            "description": "Actions revealed when swiping right. Each: { key?, label, icon?, color?, onTrigger?, fullSwipe?, background?, ariaLabel? }."
          },
          "rightActions": {
            "type": "SwipeableAction[]",
            "description": "Actions revealed when swiping left."
          },
          "threshold": {
            "type": "number",
            "default": "0.4",
            "description": "Fraction of the actions strip width that must be swiped to open. Range 0-1."
          },
          "fullSwipeThreshold": {
            "type": "number",
            "default": "0.7",
            "description": "Fraction beyond which an action marked fullSwipe is auto-triggered without tapping."
          },
          "variant": {
            "type": "'inline' | 'card' | 'compact'",
            "default": "'inline'",
            "description": "Visual style. 'card' adds rounded corners and a border; 'compact' uses tighter padding."
          },
          "disabled": {
            "type": "boolean",
            "default": "false",
            "description": "Disable the swipe gesture."
          },
          "onSwipeOpen": {
            "type": "(side: 'left' | 'right') => void",
            "description": "Called when the row settles open on one side."
          },
          "onSwipeClose": {
            "type": "() => void",
            "description": "Called when the row returns to closed."
          },
          "closeOnSelect": {
            "type": "boolean",
            "default": "true",
            "description": "Auto-close after an action is tapped."
          },
          "className": {
            "type": "string",
            "description": "Additional CSS class for the wrapper."
          },
          "actionWidth": {
            "type": "number",
            "default": "80",
            "description": "Pixel width per revealed action button."
          }
        }
      },
      "storyDir": "swipeable-list-item"
    },
    "TabView": {
      "name": "TabView",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React, { useState } from 'react';\nimport { TabPage, TabView } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { TabView, TabPage } from 'fluxo-ui';\n\nfunction MyComponent() {\n  const [activeIndex, setActiveIndex] = useState(0);\n\n  return (\n    <TabView activeIndex={activeIndex} onTabChange={(e) => setActiveIndex(e.index)}>\n      <TabPage header=\"Dashboard\">Dashboard content</TabPage>\n      <TabPage header=\"Analytics\">Analytics content</TabPage>\n      <TabPage header=\"Settings\">Settings content</TabPage>\n    </TabView>\n  );\n}`;\n\nconst BasicUsage: React.FC = () => {\n    const [activeIndex, setActiveIndex] = useState(0);\n\n    return (\n        <>\n            <ComponentDemo title=\"Basic TabView\" description=\"Simple tab navigation with multiple panels\">\n                <TabView activeIndex={activeIndex} onTabChange={(e) => setActiveIndex(e.index)}>\n                    <TabPage header=\"Dashboard\">\n                        <div className=\"p-4\">\n                            <h3 className=\"text-lg font-semibold mb-2\">Dashboard</h3>\n                            <p>Welcome to the dashboard. Here you can see an overview of your data.</p>\n                        </div>\n                    </TabPage>\n                    <TabPage header=\"Analytics\">\n                        <div className=\"p-4\">\n                            <h3 className=\"text-lg font-semibold mb-2\">Analytics</h3>\n                            <p>View detailed analytics and reports about your performance.</p>\n                        </div>\n                    </TabPage>\n                    <TabPage header=\"Settings\">\n                        <div className=\"p-4\">\n                            <h3 className=\"text-lg font-semibold mb-2\">Settings</h3>\n                            <p>Configure your application settings and preferences.</p>\n                        </div>\n                    </TabPage>\n                </TabView>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "ClosableTabs",
          "code": "import React, { useState } from 'react';\nimport { TabPage, TabView } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<TabView\n  activeIndex={activeIndex}\n  onTabChange={(e) => setActiveIndex(e.index)}\n  onTabClose={(e) => {\n    setTabs(tabs.filter((_, i) => i !== e.index));\n    if (e.index <= activeIndex) setActiveIndex(Math.max(0, activeIndex - 1));\n  }}\n>\n  {tabs.map((tab) => (\n    <TabPage key={tab} header={tab} closable>\n      Content of {tab}\n    </TabPage>\n  ))}\n</TabView>`;\n\nconst initialTabs = ['index.tsx', 'App.tsx', 'utils.ts', 'styles.css', 'README.md'];\n\nconst ClosableTabs: React.FC = () => {\n    const [tabs, setTabs] = useState(initialTabs);\n    const [activeIndex, setActiveIndex] = useState(0);\n\n    const handleClose = (index: number) => {\n        const newTabs = tabs.filter((_, i) => i !== index);\n        setTabs(newTabs);\n        if (index <= activeIndex && activeIndex > 0) {\n            setActiveIndex(activeIndex - 1);\n        } else if (index < activeIndex) {\n            setActiveIndex(activeIndex - 1);\n        }\n    };\n\n    const handleReset = () => {\n        setTabs(initialTabs);\n        setActiveIndex(0);\n    };\n\n    return (\n        <>\n            <ComponentDemo title=\"Closable Tabs\" description=\"Tabs with close buttons for dynamic tab management\">\n                <div className=\"w-full\">\n                    <TabView\n                        activeIndex={activeIndex}\n                        onTabChange={(e) => setActiveIndex(e.index)}\n                        onTabClose={(e) => handleClose(e.index)}\n                    >\n                        {tabs.map((tab) => (\n                            <TabPage key={tab} header={tab} closable>\n                                <div className=\"p-4\">\n                                    <p>Content of <strong>{tab}</strong></p>\n                                </div>\n                            </TabPage>\n                        ))}\n                    </TabView>\n                    {tabs.length === 0 && (\n                        <div className=\"p-4 text-center\">\n                            <p className=\"mb-3 opacity-60\">All tabs closed</p>\n                            <button className=\"px-3 py-1.5 text-sm rounded-md bg-blue-500 text-white\" onClick={handleReset}>\n                                Reset Tabs\n                            </button>\n                        </div>\n                    )}\n                    {tabs.length > 0 && tabs.length < initialTabs.length && (\n                        <div className=\"mt-2 text-right\">\n                            <button className=\"px-2 py-1 text-xs rounded opacity-60 hover:opacity-100\" onClick={handleReset}>\n                                Reset\n                            </button>\n                        </div>\n                    )}\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default ClosableTabs;\n"
        },
        {
          "title": "EventHandling",
          "code": "import React from 'react';\nimport { CodeBlock } from '../../CodeBlock';\n\nconst eventCode = `import { TabView, TabPage, TabChangeEvent, TabCloseEvent } from 'fluxo-ui';\n\nfunction MyComponent() {\n  const handleTabChange = (e: TabChangeEvent) => {\n    console.log('Tab changed to index:', e.index);\n  };\n\n  const handleBeforeTabChange = (e: TabChangeEvent) => {\n    if (e.index === 2) {\n      alert('Cannot switch to this tab');\n      return false;\n    }\n    return true;\n  };\n\n  const handleTabClose = (e: TabCloseEvent) => {\n    console.log('Closing tab at index:', e.index);\n  };\n\n  return (\n    <TabView\n      onTabChange={handleTabChange}\n      onBeforeTabChange={handleBeforeTabChange}\n      onTabClose={handleTabClose}\n    >\n      <TabPage header=\"Allowed\">Content 1</TabPage>\n      <TabPage header=\"Allowed\">Content 2</TabPage>\n      <TabPage header=\"Restricted\">Content 3</TabPage>\n    </TabView>\n  );\n}`;\n\nconst EventHandling: React.FC = () => <CodeBlock code={eventCode} language=\"tsx\" />;\n\nexport default EventHandling;\n"
        },
        {
          "title": "HeaderEnd",
          "code": "import React, { useState } from 'react';\nimport { TabPage, TabView } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<TabView\n  headerEnd={<button className=\"...\">+ Add Tab</button>}\n>\n  <TabPage header=\"Tab 1\">Content</TabPage>\n  <TabPage header=\"Tab 2\">Content</TabPage>\n</TabView>`;\n\nconst HeaderEnd: React.FC = () => {\n    const [activeIndex, setActiveIndex] = useState(0);\n\n    return (\n        <>\n            <ComponentDemo title=\"Header End Content\" description=\"Custom content in the tab header row's trailing space\">\n                <TabView\n                    activeIndex={activeIndex}\n                    onTabChange={(e) => setActiveIndex(e.index)}\n                    headerEnd={\n                        <div className=\"flex items-center gap-2\">\n                            <button className=\"px-2 py-1 text-xs rounded-md bg-blue-500 text-white hover:bg-blue-600\">+ New</button>\n                            <button className=\"px-2 py-1 text-xs rounded-md border border-current opacity-60 hover:opacity-100\">\n                                <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" className=\"w-3.5 h-3.5\">\n                                    <circle cx=\"12\" cy=\"12\" r=\"1\" /><circle cx=\"19\" cy=\"12\" r=\"1\" /><circle cx=\"5\" cy=\"12\" r=\"1\" />\n                                </svg>\n                            </button>\n                        </div>\n                    }\n                >\n                    <TabPage header=\"Overview\">\n                        <div className=\"p-4\"><p>Overview content with a trailing action button.</p></div>\n                    </TabPage>\n                    <TabPage header=\"Details\">\n                        <div className=\"p-4\"><p>Details content.</p></div>\n                    </TabPage>\n                    <TabPage header=\"History\">\n                        <div className=\"p-4\"><p>History content.</p></div>\n                    </TabPage>\n                </TabView>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default HeaderEnd;\n"
        },
        {
          "title": "Positions",
          "code": "import React, { useState } from 'react';\nimport { TabPage, TabView } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<TabView position=\"left\">\n  <TabPage header=\"Profile\">Profile content</TabPage>\n  <TabPage header=\"Account\">Account content</TabPage>\n  <TabPage header=\"Security\">Security content</TabPage>\n</TabView>\n\n<TabView position=\"right\">...</TabView>\n<TabView position=\"bottom\">...</TabView>`;\n\nconst tabs = ['Profile', 'Account', 'Security'];\n\nconst Positions: React.FC = () => {\n    const [leftIdx, setLeftIdx] = useState(0);\n    const [rightIdx, setRightIdx] = useState(0);\n    const [bottomIdx, setBottomIdx] = useState(0);\n\n    const renderContent = (name: string) => (\n        <div className=\"p-4\">\n            <h3 className=\"text-lg font-semibold mb-2\">{name}</h3>\n            <p>Manage your {name.toLowerCase()} information and preferences.</p>\n        </div>\n    );\n\n    return (\n        <>\n            <div className=\"space-y-6\">\n                <ComponentDemo title=\"Left Position\" description=\"Tab headers positioned on the left side\">\n                    <div className=\"h-48\">\n                        <TabView activeIndex={leftIdx} onTabChange={(e) => setLeftIdx(e.index)} position=\"left\">\n                            {tabs.map((t) => (\n                                <TabPage key={t} header={t}>{renderContent(t)}</TabPage>\n                            ))}\n                        </TabView>\n                    </div>\n                </ComponentDemo>\n\n                <ComponentDemo title=\"Right Position\" description=\"Tab headers positioned on the right side\">\n                    <div className=\"h-48\">\n                        <TabView activeIndex={rightIdx} onTabChange={(e) => setRightIdx(e.index)} position=\"right\">\n                            {tabs.map((t) => (\n                                <TabPage key={t} header={t}>{renderContent(t)}</TabPage>\n                            ))}\n                        </TabView>\n                    </div>\n                </ComponentDemo>\n\n                <ComponentDemo title=\"Bottom Position\" description=\"Tab headers at the bottom\">\n                    <TabView activeIndex={bottomIdx} onTabChange={(e) => setBottomIdx(e.index)} position=\"bottom\">\n                        {tabs.map((t) => (\n                            <TabPage key={t} header={t}>{renderContent(t)}</TabPage>\n                        ))}\n                    </TabView>\n                </ComponentDemo>\n            </div>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default Positions;\n"
        },
        {
          "title": "ScrollableTabs",
          "code": "import React, { useState } from 'react';\nimport { TabPage, TabView } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<TabView scrollable activeIndex={activeIndex} onTabChange={(e) => setActiveIndex(e.index)}>\n  <TabPage header=\"Home\">Home content</TabPage>\n  <TabPage header=\"Products\">Products content</TabPage>\n  <TabPage header=\"Services\">Services content</TabPage>\n  <TabPage header=\"About\">About content</TabPage>\n  <TabPage header=\"Contact\">Contact content</TabPage>\n  <TabPage header=\"Support\">Support content</TabPage>\n  <TabPage header=\"Documentation\">Docs content</TabPage>\n</TabView>`;\n\nconst tabNames = ['Home', 'Products', 'Services', 'About Us', 'Contact', 'Support', 'Documentation', 'Blog'];\n\nconst ScrollableTabs: React.FC = () => {\n    const [activeIndex, setActiveIndex] = useState(0);\n\n    return (\n        <>\n            <ComponentDemo title=\"Scrollable Tabs\" description=\"Tab navigation with scroll arrows when tabs overflow\">\n                <div className=\"w-full max-w-md\">\n                    <TabView activeIndex={activeIndex} onTabChange={(e) => setActiveIndex(e.index)} scrollable>\n                        {tabNames.map((name) => (\n                            <TabPage key={name} header={name}>\n                                <div className=\"p-4\">\n                                    <h3 className=\"text-lg font-semibold mb-2\">{name}</h3>\n                                    <p>{name} page content goes here.</p>\n                                </div>\n                            </TabPage>\n                        ))}\n                    </TabView>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default ScrollableTabs;\n"
        },
        {
          "title": "StyleVariants",
          "code": "import React, { useState } from 'react';\nimport { TabPage, TabView } from '../../../components';\nimport type { TabViewVariant } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<TabView variant=\"pills\">...</TabView>\n<TabView variant=\"enclosed\">...</TabView>\n<TabView variant=\"segment\">...</TabView>\n<TabView variant=\"editor\">...</TabView>\n<TabView variant=\"thick-border\">...</TabView>\n<TabView variant=\"elevated\">...</TabView>\n<TabView variant=\"glow\">...</TabView>`;\n\nconst variants: { name: string; variant: TabViewVariant; description: string }[] = [\n    { name: 'Default', variant: 'default', description: 'Standard underline indicator' },\n    { name: 'Pills', variant: 'pills', description: 'Rounded pill-shaped active indicator with filled background' },\n    { name: 'Enclosed', variant: 'enclosed', description: 'Browser-style tabs with bordered active panel' },\n    { name: 'Segment', variant: 'segment', description: 'iOS-style segmented control with subtle background' },\n    { name: 'Editor', variant: 'editor', description: 'VS Code / code editor style with top accent border' },\n    { name: 'Thick Border', variant: 'thick-border', description: 'Bold top border highlight for the active tab' },\n    { name: 'Elevated', variant: 'elevated', description: 'Larger active tab with font size change and thick bottom border' },\n    { name: 'Glow', variant: 'glow', description: 'Pill track with an animated, primary-tinted glowing indicator that slides behind the active tab' },\n];\n\nconst tabContent = [\n    { header: 'Dashboard', content: 'Overview of your workspace and recent activity.' },\n    { header: 'Analytics', content: 'Charts and insights about your data trends.' },\n    { header: 'Settings', content: 'Configure preferences and manage your account.' },\n];\n\nconst StyleVariants: React.FC = () => {\n    const [indices, setIndices] = useState<Record<string, number>>({});\n\n    const getIndex = (variant: string) => indices[variant] ?? 0;\n    const setIndex = (variant: string, idx: number) => setIndices((prev) => ({ ...prev, [variant]: idx }));\n\n    return (\n        <>\n            <div className=\"space-y-6\">\n                {variants.map(({ name, variant, description }) => (\n                    <ComponentDemo key={variant} title={name} description={description}>\n                        <TabView\n                            variant={variant}\n                            activeIndex={getIndex(variant)}\n                            onTabChange={(e) => setIndex(variant, e.index)}\n                        >\n                            {tabContent.map((tab) => (\n                                <TabPage key={tab.header} header={tab.header}>\n                                    <div className=\"p-4\"><p>{tab.content}</p></div>\n                                </TabPage>\n                            ))}\n                        </TabView>\n                    </ComponentDemo>\n                ))}\n            </div>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default StyleVariants;\n"
        },
        {
          "title": "WithIcons",
          "code": "import React, { useState } from 'react';\nimport { TabPage, TabView } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst homeIcon = (\n    <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n        <path d=\"M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z\" />\n        <polyline points=\"9 22 9 12 15 12 15 22\" />\n    </svg>\n);\n\nconst chartIcon = (\n    <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n        <line x1=\"18\" y1=\"20\" x2=\"18\" y2=\"10\" />\n        <line x1=\"12\" y1=\"20\" x2=\"12\" y2=\"4\" />\n        <line x1=\"6\" y1=\"20\" x2=\"6\" y2=\"14\" />\n    </svg>\n);\n\nconst settingsIcon = (\n    <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n        <circle cx=\"12\" cy=\"12\" r=\"3\" />\n        <path d=\"M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z\" />\n    </svg>\n);\n\nconst userIcon = (\n    <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n        <path d=\"M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2\" />\n        <circle cx=\"12\" cy=\"7\" r=\"4\" />\n    </svg>\n);\n\nconst bellIcon = (\n    <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n        <path d=\"M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9\" />\n        <path d=\"M13.73 21a2 2 0 0 1-3.46 0\" />\n    </svg>\n);\n\nconst badgeIcon = (\n    <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n        <circle cx=\"12\" cy=\"12\" r=\"10\" />\n        <line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"12\" />\n        <line x1=\"12\" y1=\"16\" x2=\"12.01\" y2=\"16\" />\n    </svg>\n);\n\nconst leftIconCode = `<TabView>\n  <TabPage header=\"Home\" leftIcon={<HomeIcon />}>Home</TabPage>\n  <TabPage header=\"Analytics\" leftIcon={<ChartIcon />}>Analytics</TabPage>\n  <TabPage header=\"Settings\" leftIcon={<SettingsIcon />}>Settings</TabPage>\n</TabView>`;\n\nconst bothIconsCode = `<TabView>\n  <TabPage header=\"Profile\" leftIcon={<UserIcon />} rightIcon={<BadgeIcon />}>\n    Profile\n  </TabPage>\n  <TabPage header=\"Notifications\" leftIcon={<BellIcon />} rightIcon={<BadgeIcon />}>\n    Notifications\n  </TabPage>\n</TabView>`;\n\nconst WithIcons: React.FC = () => {\n    const [leftIdx, setLeftIdx] = useState(0);\n    const [bothIdx, setBothIdx] = useState(0);\n    const [disabledIdx, setDisabledIdx] = useState(0);\n\n    return (\n        <>\n            <div className=\"space-y-6\">\n                <ComponentDemo title=\"Left Icons\" description=\"SVG icons on the left side of tab headers\">\n                    <TabView activeIndex={leftIdx} onTabChange={(e) => setLeftIdx(e.index)}>\n                        <TabPage header=\"Home\" leftIcon={homeIcon}>\n                            <div className=\"p-4\">\n                                <p>Welcome to the home page with a home icon.</p>\n                            </div>\n                        </TabPage>\n                        <TabPage header=\"Analytics\" leftIcon={chartIcon}>\n                            <div className=\"p-4\">\n                                <p>View analytics data with a chart icon.</p>\n                            </div>\n                        </TabPage>\n                        <TabPage header=\"Settings\" leftIcon={settingsIcon}>\n                            <div className=\"p-4\">\n                                <p>Configure your settings with a gear icon.</p>\n                            </div>\n                        </TabPage>\n                    </TabView>\n                </ComponentDemo>\n\n                <ComponentDemo title=\"Left & Right Icons\" description=\"Icons on both sides of tab headers\">\n                    <TabView activeIndex={bothIdx} onTabChange={(e) => setBothIdx(e.index)}>\n                        <TabPage header=\"Profile\" leftIcon={userIcon} rightIcon={badgeIcon}>\n                            <div className=\"p-4\">\n                                <p>User profile with both left and right icons.</p>\n                            </div>\n                        </TabPage>\n                        <TabPage header=\"Notifications\" leftIcon={bellIcon} rightIcon={badgeIcon}>\n                            <div className=\"p-4\">\n                                <p>Notifications with bell icon and badge indicator.</p>\n                            </div>\n                        </TabPage>\n                        <TabPage header=\"Settings\" leftIcon={settingsIcon}>\n                            <div className=\"p-4\">\n                                <p>Settings with only a left icon.</p>\n                            </div>\n                        </TabPage>\n                    </TabView>\n                </ComponentDemo>\n\n                <ComponentDemo title=\"With Disabled Tab\" description=\"Tabs with icons and a disabled state\">\n                    <TabView activeIndex={disabledIdx} onTabChange={(e) => setDisabledIdx(e.index)}>\n                        <TabPage header=\"Home\" leftIcon={homeIcon}>\n                            <div className=\"p-4\"><p>Active tab content.</p></div>\n                        </TabPage>\n                        <TabPage header=\"Analytics\" leftIcon={chartIcon}>\n                            <div className=\"p-4\"><p>Analytics content.</p></div>\n                        </TabPage>\n                        <TabPage header=\"Restricted\" leftIcon={settingsIcon} disabled>\n                            <div className=\"p-4\"><p>This tab is disabled.</p></div>\n                        </TabPage>\n                    </TabView>\n                </ComponentDemo>\n            </div>\n            <div className=\"mt-4 space-y-4\">\n                <CodeBlock code={leftIconCode} language=\"tsx\" />\n                <CodeBlock code={bothIconsCode} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default WithIcons;\n"
        }
      ],
      "props": {
        "tabViewProps": {
          "activeIndex": {
            "type": "number",
            "default": "0",
            "description": "Index of the active tab"
          },
          "onTabChange": {
            "type": "(e: TabChangeEvent) => void",
            "description": "Callback fired when tab changes"
          },
          "onBeforeTabChange": {
            "type": "(e: TabChangeEvent) => boolean | Promise<boolean>",
            "description": "Callback before tab changes. Return false to prevent change."
          },
          "onTabClose": {
            "type": "(e: TabCloseEvent) => void",
            "description": "Callback when a closable tab is closed"
          },
          "headerEnd": {
            "type": "React.ReactNode",
            "description": "Content rendered at the trailing end of the tab header row"
          },
          "variant": {
            "type": "'default' | 'pills' | 'enclosed' | 'segment' | 'editor' | 'thick-border' | 'elevated' | 'glow'",
            "default": "'default'",
            "description": "Visual style variant. 'glow' renders a pill track with an animated, primary-tinted glowing indicator that slides behind the active tab."
          },
          "scrollable": {
            "type": "boolean",
            "default": "false",
            "description": "Show scroll arrows when tabs overflow"
          },
          "position": {
            "type": "'top' | 'bottom' | 'left' | 'right'",
            "default": "'top'",
            "description": "Position of tab headers"
          },
          "activationMode": {
            "type": "'auto' | 'manual'",
            "default": "'auto'",
            "description": "How tabs activate via keyboard. 'auto' selects on arrow-key navigation; 'manual' moves focus only and requires Enter/Space to activate."
          },
          "ariaLabel": {
            "type": "string",
            "description": "Accessible name for the tablist (announced by screen readers when entering the tabs)."
          },
          "preMount": {
            "type": "boolean",
            "default": "false",
            "description": "Render all tab panels at once (hiding inactive ones) instead of mounting only the active panel."
          },
          "className": {
            "type": "string",
            "description": "Additional CSS class names"
          },
          "style": {
            "type": "React.CSSProperties",
            "description": "Inline styles"
          },
          "children": {
            "type": "React.ReactNode",
            "description": "TabPage components"
          }
        },
        "tabPageProps": {
          "header": {
            "type": "React.ReactNode",
            "required": true,
            "description": "Tab header content"
          },
          "leftIcon": {
            "type": "string | React.ComponentType | React.ReactElement",
            "description": "Icon on the left side of the header"
          },
          "rightIcon": {
            "type": "string | React.ComponentType | React.ReactElement",
            "description": "Icon on the right side of the header"
          },
          "closable": {
            "type": "boolean",
            "default": "false",
            "description": "Show a close button on the tab header"
          },
          "visible": {
            "type": "boolean",
            "default": "true",
            "description": "Whether the tab is visible"
          },
          "disabled": {
            "type": "boolean",
            "default": "false",
            "description": "Whether the tab is disabled"
          },
          "className": {
            "type": "string",
            "description": "CSS class for tab content panel"
          },
          "style": {
            "type": "React.CSSProperties",
            "description": "Inline styles for tab content panel"
          },
          "children": {
            "type": "React.ReactNode",
            "description": "Tab panel content"
          }
        }
      },
      "storyDir": "tab-view"
    },
    "Table": {
      "name": "Table",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React from 'react';\nimport Table from '../../../components/table/Table';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { basicColumns, sampleUsers } from './table-story-data';\n\nconst code = `import { Table } from 'fluxo-ui';\n\nconst columns = [\n  { title: 'ID', field: 'id', sortable: true },\n  { title: 'Name', field: 'name', sortable: true },\n  { title: 'Email', field: 'email', sortable: true },\n  { title: 'Role', field: 'role', sortable: true },\n];\n\n<Table columns={columns} rows={data} totalRows={data.length} pagination={false} />`;\n\nconst BasicUsage: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Basic Table\" centered={false}>\n            <Table columns={basicColumns} rows={sampleUsers.slice(0, 5)} totalRows={5} pagination={false} />\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default BasicUsage;\n"
        },
        {
          "title": "CustomRendering",
          "code": "import React from 'react';\nimport Table from '../../../components/table/Table';\nimport { Column } from '../../../components/table/table-types';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { sampleUsers, User } from './table-story-data';\n\nconst customColumns: Column[] = [\n    { title: 'ID', field: 'id', sortable: true, cellClassName: 'font-mono text-gray-500' },\n    { title: 'Name', field: 'name', sortable: true, cellClassName: 'font-semibold' },\n    { title: 'Email', field: 'email', sortable: true },\n    {\n        title: 'Status',\n        field: 'status',\n        sortable: true,\n        template: (row: User) => (\n            <span\n                className={`px-2 py-1 rounded text-xs ${\n                    row.status === 'active'\n                        ? 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200'\n                        : 'bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200'\n                }`}\n            >\n                {row.status}\n            </span>\n        ),\n    },\n    { title: 'Join Date', field: 'joinDate', sortable: true },\n];\n\nconst code = `{\n  title: 'Status',\n  field: 'status',\n  template: (row) => (\n    <span className={row.status === 'active' ? 'badge-green' : 'badge-red'}>\n      {row.status}\n    </span>\n  ),\n}`;\n\nconst CustomRendering: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Table with Custom Templates\" description=\"Custom cell rendering with badges\" centered={false}>\n            <Table columns={customColumns} rows={sampleUsers} totalRows={sampleUsers.length} pagination={false} />\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default CustomRendering;\n"
        },
        {
          "title": "LoadingAndEmpty",
          "code": "import React, { useState } from 'react';\nimport { Button } from '../../../components';\nimport Table from '../../../components/table/Table';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { basicColumns, sampleUsers } from './table-story-data';\n\nconst loadingCode = `<Table\n  columns={columns}\n  rows={data}\n  totalRows={data.length}\n  isLoading={isLoading}\n  expectedRows={5}\n/>`;\n\nconst emptyCode = `<Table\n  columns={columns}\n  rows={[]}\n  totalRows={0}\n  noRowsMessage=\"No users found. Try adjusting your filters.\"\n  pagination={false}\n/>`;\n\nconst LoadingAndEmpty: React.FC = () => {\n    const [isLoading, setIsLoading] = useState(false);\n\n    const handleLoadingDemo = () => {\n        setIsLoading(true);\n        setTimeout(() => setIsLoading(false), 2000);\n    };\n\n    return (\n        <>\n            <div className=\"space-y-6\">\n                <ComponentDemo title=\"Loading State\" description=\"Shimmer skeleton while data loads\" centered={false}>\n                    <div className=\"space-y-4\">\n                        <Button onClick={handleLoadingDemo} variant=\"primary\">Simulate Loading</Button>\n                        <Table\n                            columns={basicColumns}\n                            rows={sampleUsers}\n                            totalRows={sampleUsers.length}\n                            isLoading={isLoading}\n                            expectedRows={5}\n                            pagination={false}\n                        />\n                    </div>\n                </ComponentDemo>\n\n                <ComponentDemo title=\"Empty State\" description=\"Custom message when no data\" centered={false}>\n                    <Table\n                        columns={basicColumns}\n                        rows={[]}\n                        totalRows={0}\n                        noRowsMessage=\"No users found. Try adjusting your filters.\"\n                        pagination={false}\n                    />\n                </ComponentDemo>\n            </div>\n            <div className=\"mt-4 space-y-4\">\n                <CodeBlock code={loadingCode} language=\"tsx\" />\n                <CodeBlock code={emptyCode} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default LoadingAndEmpty;\n"
        },
        {
          "title": "ResponsiveColumns",
          "code": "import React from 'react';\nimport Table from '../../../components/table/Table';\nimport { Column } from '../../../components/table/table-types';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { sampleUsers } from './table-story-data';\n\nconst responsiveColumns: Column[] = [\n    { title: 'ID', field: 'id', sortable: true },\n    { title: 'Name', field: 'name', sortable: true },\n    { title: 'Email', field: 'email', sortable: true, hideBelow: 'md' },\n    { title: 'Role', field: 'role', sortable: true, hideBelow: 'sm' },\n    { title: 'Department', field: 'department', sortable: true, hideBelow: 'lg' },\n    { title: 'Join Date', field: 'joinDate', sortable: true, hideBelow: 'xl' },\n];\n\nconst code = `const columns = [\n  { title: 'ID', field: 'id' },\n  { title: 'Name', field: 'name' },\n  { title: 'Email', field: 'email', hideBelow: 'md' },\n  { title: 'Role', field: 'role', hideBelow: 'sm' },\n  { title: 'Department', field: 'department', hideBelow: 'lg' },\n  { title: 'Join Date', field: 'joinDate', hideBelow: 'xl' },\n];`;\n\nconst ResponsiveColumns: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Responsive Columns\" description=\"Resize the browser to see columns hide at breakpoints\" centered={false}>\n            <Table columns={responsiveColumns} rows={sampleUsers} totalRows={sampleUsers.length} rowsPerPage={5} />\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default ResponsiveColumns;\n"
        },
        {
          "title": "RowSelection",
          "code": "import React, { useState } from 'react';\nimport Table from '../../../components/table/Table';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { basicColumns, sampleUsers, User } from './table-story-data';\n\nconst code = `<Table\n  columns={columns}\n  rows={data}\n  totalRows={data.length}\n  onRowClick={({ row }) => setSelectedRow(row)}\n  pagination={false}\n/>`;\n\nconst RowSelection: React.FC = () => {\n    const [selectedRow, setSelectedRow] = useState<User | null>(null);\n\n    return (\n        <>\n            <ComponentDemo title=\"Table with Row Click\" centered={false}>\n                <div className=\"space-y-4\">\n                    <Table\n                        columns={basicColumns}\n                        rows={sampleUsers.slice(0, 5)}\n                        totalRows={5}\n                        pagination={false}\n                        onRowClick={({ row }) => setSelectedRow(row)}\n                    />\n                    {selectedRow && (\n                        <div className=\"p-4 bg-blue-50 dark:bg-blue-900 rounded border border-blue-200 dark:border-blue-700\">\n                            <p className=\"text-sm font-semibold text-blue-900 dark:text-blue-100\">\n                                Selected: {selectedRow.name} ({selectedRow.email})\n                            </p>\n                        </div>\n                    )}\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default RowSelection;\n"
        },
        {
          "title": "SortableColumns",
          "code": "import React from 'react';\nimport Table from '../../../components/table/Table';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { basicColumns, sampleUsers } from './table-story-data';\n\nconst code = `<Table\n  columns={columns}\n  rows={data}\n  totalRows={data.length}\n  onSort={(column, asc) => console.log('Sort by:', column.field, asc)}\n  pagination={false}\n/>`;\n\nconst SortableColumns: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Table with Sorting\" description=\"Click column headers to sort\" centered={false}>\n            <Table\n                columns={basicColumns}\n                rows={sampleUsers}\n                totalRows={sampleUsers.length}\n                onSort={(col, asc) => console.log('Sort:', col.field, asc)}\n                pagination={false}\n            />\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default SortableColumns;\n"
        },
        {
          "title": "StyleVariants",
          "code": "import React from 'react';\nimport Table from '../../../components/table/Table';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { basicColumns, fullColumns, sampleUsers } from './table-story-data';\n\nconst code = `<Table bordered columns={columns} rows={data} totalRows={data.length} pagination={false} />\n<Table striped columns={columns} rows={data} totalRows={data.length} pagination={false} />\n<Table compact columns={columns} rows={data} totalRows={data.length} pagination={false} />\n<Table comfortable columns={columns} rows={data} totalRows={data.length} pagination={false} />\n<Table borderless columns={columns} rows={data} totalRows={data.length} pagination={false} />\n<Table hoverable columns={columns} rows={data} totalRows={data.length} pagination={false} />\n<Table cardStyle columns={columns} rows={data} totalRows={data.length} pagination={false} />\n<Table minimalHeader columns={columns} rows={data} totalRows={data.length} pagination={false} />\n<Table stickyHeader maxHeight={200} columns={columns} rows={data} totalRows={data.length} pagination={false} />\n<Table striped compact bordered columns={columns} rows={data} totalRows={data.length} pagination={false} />`;\n\nconst rows5 = sampleUsers.slice(0, 5);\n\nconst StyleVariants: React.FC = () => (\n    <>\n        <div className=\"space-y-6\">\n            <ComponentDemo title=\"Bordered\" description=\"All cell borders visible\" centered={false}>\n                <Table bordered columns={basicColumns} rows={rows5} totalRows={5} pagination={false} />\n            </ComponentDemo>\n\n            <ComponentDemo title=\"Striped\" description=\"Alternating row background colors\" centered={false}>\n                <Table striped columns={basicColumns} rows={sampleUsers} totalRows={sampleUsers.length} pagination={false} />\n            </ComponentDemo>\n\n            <ComponentDemo title=\"Compact\" description=\"Reduced padding for dense data display\" centered={false}>\n                <Table compact columns={fullColumns} rows={sampleUsers} totalRows={sampleUsers.length} pagination={false} />\n            </ComponentDemo>\n\n            <ComponentDemo title=\"Comfortable\" description=\"Increased padding for readability\" centered={false}>\n                <Table comfortable columns={basicColumns} rows={rows5} totalRows={5} pagination={false} />\n            </ComponentDemo>\n\n            <ComponentDemo title=\"Borderless\" description=\"No borders or shadow for a clean look\" centered={false}>\n                <Table borderless columns={basicColumns} rows={rows5} totalRows={5} pagination={false} />\n            </ComponentDemo>\n\n            <ComponentDemo title=\"Hoverable\" description=\"Primary-color row hover highlight\" centered={false}>\n                <Table hoverable columns={basicColumns} rows={rows5} totalRows={5} pagination={false} />\n            </ComponentDemo>\n\n            <ComponentDemo title=\"Card Style\" description=\"Each row rendered as an individual card\" centered={false}>\n                <Table cardStyle columns={basicColumns} rows={rows5} totalRows={5} pagination={false} />\n            </ComponentDemo>\n\n            <ComponentDemo title=\"Minimal Header\" description=\"Subtle uppercase header with no background\" centered={false}>\n                <Table minimalHeader columns={basicColumns} rows={rows5} totalRows={5} pagination={false} />\n            </ComponentDemo>\n\n            <ComponentDemo title=\"Sticky Header\" description=\"Header stays fixed when scrolling (use the maxHeight prop to make the table itself scrollable)\" centered={false}>\n                <Table stickyHeader maxHeight={200} columns={basicColumns} rows={sampleUsers} totalRows={sampleUsers.length} pagination={false} />\n            </ComponentDemo>\n\n            <ComponentDemo title=\"Combined: Striped + Compact + Bordered\" description=\"Multiple variants can be combined\" centered={false}>\n                <Table striped compact bordered columns={fullColumns} rows={sampleUsers} totalRows={sampleUsers.length} pagination={false} />\n            </ComponentDemo>\n        </div>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default StyleVariants;\n"
        },
        {
          "title": "WithActions",
          "code": "import React from 'react';\nimport { Button } from '../../../components';\nimport Table from '../../../components/table/Table';\nimport { Column } from '../../../components/table/table-types';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { sampleUsers, User } from './table-story-data';\n\nconst columnsWithActions: Column[] = [\n    { title: 'Name', field: 'name', sortable: true },\n    { title: 'Email', field: 'email', sortable: true },\n    { title: 'Role', field: 'role', sortable: true },\n    {\n        title: 'Actions',\n        field: 'id',\n        template: (row: User) => (\n            <div className=\"flex gap-2\">\n                <Button size=\"xs\" variant=\"primary\" onClick={(e) => { e.stopPropagation(); alert(`Edit ${row.name}`); }}>\n                    Edit\n                </Button>\n                <Button size=\"xs\" variant=\"danger\" layout=\"outlined\" onClick={(e) => { e.stopPropagation(); alert(`Delete ${row.name}`); }}>\n                    Delete\n                </Button>\n            </div>\n        ),\n    },\n];\n\nconst code = `{\n  title: 'Actions',\n  field: 'id',\n  template: (row) => (\n    <div className=\"flex gap-2\">\n      <Button size=\"xs\" variant=\"primary\" onClick={() => handleEdit(row)}>Edit</Button>\n      <Button size=\"xs\" variant=\"danger\" layout=\"outlined\" onClick={() => handleDelete(row)}>Delete</Button>\n    </div>\n  ),\n}`;\n\nconst WithActions: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Table with Row Actions\" centered={false}>\n            <Table columns={columnsWithActions} rows={sampleUsers.slice(0, 5)} totalRows={5} pagination={false} />\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default WithActions;\n"
        },
        {
          "title": "WithPagination",
          "code": "import React from 'react';\nimport Table from '../../../components/table/Table';\nimport { Column } from '../../../components/table/table-types';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { sampleUsers, User } from './table-story-data';\n\nconst columns: Column[] = [\n    { title: 'ID', field: 'id', sortable: true },\n    { title: 'Name', field: 'name', sortable: true },\n    { title: 'Email', field: 'email', sortable: true },\n    {\n        title: 'Status',\n        field: 'status',\n        sortable: true,\n        template: (row: User) => (\n            <span\n                className={`px-2 py-1 rounded text-xs ${\n                    row.status === 'active'\n                        ? 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200'\n                        : 'bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200'\n                }`}\n            >\n                {row.status}\n            </span>\n        ),\n    },\n    { title: 'Join Date', field: 'joinDate', sortable: true },\n];\n\nconst code = `<Table\n  columns={columns}\n  rows={data}\n  totalRows={data.length}\n  rowsPerPage={5}\n  rowCounts={[5, 10, 15]}\n  onChange={(params) => console.log(params)}\n/>`;\n\nconst WithPagination: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Table with Pagination\" centered={false}>\n            <Table\n                columns={columns}\n                rows={sampleUsers}\n                totalRows={sampleUsers.length}\n                rowsPerPage={5}\n                rowCounts={[5, 10, 15]}\n                onChange={(params) => console.log('Table changed:', params)}\n            />\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default WithPagination;\n"
        }
      ],
      "props": {
        "tableProps": {
          "columns": {
            "type": "Column[]",
            "required": true,
            "description": "Array of column definitions"
          },
          "rows": {
            "type": "any[]",
            "required": true,
            "description": "Array of data objects to display"
          },
          "totalRows": {
            "type": "number",
            "required": true,
            "description": "Total number of rows (for pagination)"
          },
          "id": {
            "type": "string",
            "description": "HTML id for the table container"
          },
          "isLoading": {
            "type": "boolean",
            "default": "false",
            "description": "Show shimmer loading state"
          },
          "expectedRows": {
            "type": "number",
            "description": "Number of shimmer rows when loading"
          },
          "onSort": {
            "type": "(column: Column, asc: boolean) => void",
            "description": "Callback when a sortable column is clicked"
          },
          "onChange": {
            "type": "(params: OnChangeParams) => void",
            "description": "Callback for sort, pagination, or row count changes"
          },
          "noRowsMessage": {
            "type": "string",
            "default": "'No records found.'",
            "description": "Message when no rows exist"
          },
          "rowCounts": {
            "type": "number[]",
            "default": "[10, 20, 25, 50, 75, 100]",
            "description": "Options for rows per page dropdown"
          },
          "rowsPerPage": {
            "type": "number",
            "default": "rowCounts[0]",
            "description": "Initial rows per page"
          },
          "sortColumn": {
            "type": "Column",
            "description": "Initially sorted column"
          },
          "sortAsc": {
            "type": "boolean",
            "default": "true",
            "description": "Initial sort direction"
          },
          "page": {
            "type": "number",
            "default": "1",
            "description": "Initial page number"
          },
          "pagination": {
            "type": "boolean",
            "default": "true",
            "description": "Show pagination footer"
          },
          "containerClassName": {
            "type": "string",
            "description": "CSS class for the table container"
          },
          "onRowClick": {
            "type": "(arg: { row, index, event }) => void",
            "description": "Callback when a row is clicked"
          },
          "bordered": {
            "type": "boolean",
            "default": "false",
            "description": "Show all cell borders"
          },
          "striped": {
            "type": "boolean",
            "default": "false",
            "description": "Alternate row background colors"
          },
          "compact": {
            "type": "boolean",
            "default": "false",
            "description": "Reduced padding for dense display"
          },
          "comfortable": {
            "type": "boolean",
            "default": "false",
            "description": "Increased padding for readability"
          },
          "borderless": {
            "type": "boolean",
            "default": "false",
            "description": "Remove all borders and shadow"
          },
          "hoverable": {
            "type": "boolean",
            "default": "false",
            "description": "Primary-color row hover highlight"
          },
          "cardStyle": {
            "type": "boolean",
            "default": "false",
            "description": "Render each row as a card"
          },
          "minimalHeader": {
            "type": "boolean",
            "default": "false",
            "description": "Subtle uppercase header"
          },
          "stickyHeader": {
            "type": "boolean",
            "default": "false",
            "description": "Keep the header pinned to the top while the table body scrolls. Pair with maxHeight so the table-container has a scrollable height."
          },
          "maxHeight": {
            "type": "number | string",
            "description": "Cap the height of the inner scroll container. Required for stickyHeader to engage — the container itself becomes the scroll context."
          },
          "caption": {
            "type": "ReactNode",
            "description": "Visible caption rendered above the table; also used as the accessible name."
          },
          "ariaLabel": {
            "type": "string",
            "description": "Accessible name for the table when no visible caption is shown."
          },
          "ariaDescribedBy": {
            "type": "string",
            "description": "ID of an element that describes the table for screen readers."
          },
          "keyField": {
            "type": "string",
            "description": "Field name on each row used as a stable React key (avoids reconciliation issues when rows reorder)."
          },
          "mobileCardStack": {
            "type": "boolean",
            "default": "false",
            "description": "On narrow viewports, pivot rows into label/value cards instead of horizontal table rows."
          }
        },
        "columnProps": {
          "title": {
            "type": "string",
            "required": true,
            "description": "Column header text"
          },
          "field": {
            "type": "string",
            "required": true,
            "description": "Property name in the data object"
          },
          "helpText": {
            "type": "string",
            "description": "Tooltip text on the column header"
          },
          "headerClassName": {
            "type": "string",
            "description": "CSS class for the column header"
          },
          "cellClassName": {
            "type": "string",
            "description": "CSS class for cells in this column"
          },
          "sortable": {
            "type": "boolean",
            "default": "false",
            "description": "Enable sorting for this column"
          },
          "hideBelow": {
            "type": "'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl'",
            "description": "Hide column below breakpoint"
          },
          "template": {
            "type": "(row: any) => React.ReactNode",
            "description": "Custom render function for cell content"
          }
        }
      },
      "storyDir": "table"
    },
    "TimePicker": {
      "name": "TimePicker",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React, { useState } from 'react';\nimport { TimePicker } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { TimePicker } from 'fluxo-ui';\n\nconst [time, setTime] = useState<string | null>('09:30');\n\n<TimePicker value={time} onChange={(v) => setTime(v as string | null)} />\n\n<TimePicker defaultValue=\"14:45\" />\n\n<TimePicker placeholder=\"Meeting time\" />`;\n\nconst BasicUsage: React.FC = () => {\n    const [time, setTime] = useState<string | null>('09:30');\n\n    return (\n        <>\n            <ComponentDemo title=\"Default Time Picker\" description=\"24-hour format by default. Type directly or pick from the dropdown.\">\n                <div className=\"space-y-6\">\n                    <div>\n                        <div className=\"text-sm mb-2 opacity-70\">Controlled ({time ?? 'empty'})</div>\n                        <TimePicker value={time} onChange={(v) => setTime(v as string | null)} />\n                    </div>\n                    <div>\n                        <div className=\"text-sm mb-2 opacity-70\">Uncontrolled</div>\n                        <TimePicker defaultValue=\"14:45\" />\n                    </div>\n                    <div>\n                        <div className=\"text-sm mb-2 opacity-70\">Empty with placeholder</div>\n                        <TimePicker placeholder=\"Meeting time\" />\n                    </div>\n                    <div>\n                        <div className=\"text-sm mb-2 opacity-70\">Disabled</div>\n                        <TimePicker defaultValue=\"10:00\" disabled />\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "Confirm",
          "code": "import React, { useState } from 'react';\nimport { TimePicker } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<TimePicker defaultValue=\"12:00\" showConfirm autoClose={false} />\n\n<TimePicker defaultValue=\"12:00\" showNow showConfirm />\n\n<TimePicker variant=\"inline\" defaultValue=\"12:00\" format12 />`;\n\nconst Confirm: React.FC = () => {\n    const [val, setVal] = useState<Date | null>(null);\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Confirm & Inline\"\n                description=\"Require explicit confirmation before committing, or render the panel inline without a trigger.\"\n            >\n                <div className=\"space-y-6\">\n                    <div>\n                        <div className=\"text-sm mb-2 opacity-70\">Confirm button (no auto-close)</div>\n                        <TimePicker defaultValue=\"12:00\" showConfirm autoClose={false} />\n                    </div>\n                    <div>\n                        <div className=\"text-sm mb-2 opacity-70\">Now + Confirm (returns Date)</div>\n                        <TimePicker\n                            valueType=\"date\"\n                            value={val}\n                            onChange={(v) => setVal(v as Date | null)}\n                            showNow\n                            showConfirm\n                            autoClose={false}\n                        />\n                        <div className=\"text-xs mt-1 opacity-60\">Value: {val ? val.toLocaleTimeString() : '—'}</div>\n                    </div>\n                    <div>\n                        <div className=\"text-sm mb-2 opacity-70\">Inline variant</div>\n                        <TimePicker variant=\"inline\" defaultValue=\"12:00\" format12 />\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default Confirm;\n"
        },
        {
          "title": "Formats",
          "code": "import React from 'react';\nimport { TimePicker } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<TimePicker defaultValue=\"14:30\" />\n\n<TimePicker defaultValue=\"14:30\" format12 />\n\n<TimePicker defaultValue=\"14:30:45\" showSeconds />\n\n<TimePicker defaultValue=\"14:30:45\" format12 showSeconds />`;\n\nconst Formats: React.FC = () => (\n    <>\n        <ComponentDemo title=\"12/24 Hour & Seconds\" description=\"Toggle between 12-hour and 24-hour clocks, and optionally include seconds.\">\n            <div className=\"space-y-6\">\n                <div>\n                    <div className=\"text-sm mb-2 opacity-70\">24-hour (default)</div>\n                    <TimePicker defaultValue=\"14:30\" />\n                </div>\n                <div>\n                    <div className=\"text-sm mb-2 opacity-70\">12-hour</div>\n                    <TimePicker defaultValue=\"14:30\" format12 />\n                </div>\n                <div>\n                    <div className=\"text-sm mb-2 opacity-70\">24-hour with seconds</div>\n                    <TimePicker defaultValue=\"14:30:45\" showSeconds />\n                </div>\n                <div>\n                    <div className=\"text-sm mb-2 opacity-70\">12-hour with seconds</div>\n                    <TimePicker defaultValue=\"14:30:45\" format12 showSeconds />\n                </div>\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default Formats;\n"
        },
        {
          "title": "Sizes",
          "code": "import React from 'react';\nimport { TimePicker } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<TimePicker size=\"sm\" defaultValue=\"09:30\" />\n<TimePicker size=\"md\" defaultValue=\"09:30\" />\n<TimePicker size=\"lg\" defaultValue=\"09:30\" />`;\n\nconst Sizes: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Sizes\" description=\"Three trigger sizes for different form densities.\">\n            <div className=\"space-y-4\">\n                {(['sm', 'md', 'lg'] as const).map((s) => (\n                    <div key={s} className=\"flex items-center gap-4\">\n                        <span className=\"text-xs opacity-60 w-8\">{s}</span>\n                        <TimePicker size={s} defaultValue=\"09:30\" />\n                    </div>\n                ))}\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default Sizes;\n"
        },
        {
          "title": "Steps",
          "code": "import React from 'react';\nimport { TimePicker } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<TimePicker defaultValue=\"09:00\" minuteStep={15} />\n\n<TimePicker defaultValue=\"09:00\" minuteStep={5} />\n\n<TimePicker defaultValue=\"09:00:00\" showSeconds secondStep={10} />`;\n\nconst Steps: React.FC = () => (\n    <>\n        <ComponentDemo\n            title=\"Step Increments\"\n            description=\"Limit the options in each column with hourStep, minuteStep, and secondStep. Great for appointment slots.\"\n        >\n            <div className=\"space-y-6\">\n                <div>\n                    <div className=\"text-sm mb-2 opacity-70\">15-minute slots</div>\n                    <TimePicker defaultValue=\"09:00\" minuteStep={15} />\n                </div>\n                <div>\n                    <div className=\"text-sm mb-2 opacity-70\">5-minute slots</div>\n                    <TimePicker defaultValue=\"09:00\" minuteStep={5} />\n                </div>\n                <div>\n                    <div className=\"text-sm mb-2 opacity-70\">2-hour slots, 10-second precision</div>\n                    <TimePicker defaultValue=\"08:00:00\" hourStep={2} showSeconds secondStep={10} />\n                </div>\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default Steps;\n"
        }
      ],
      "props": {
        "timePickerProps": {
          "value": {
            "type": "Date | string | TimeValue | null",
            "description": "Controlled time value. Accepts Date, string (HH:mm[:ss]), or object."
          },
          "defaultValue": {
            "type": "Date | string | TimeValue | null",
            "description": "Initial value for uncontrolled usage."
          },
          "format12": {
            "type": "boolean",
            "default": "false",
            "description": "Use 12-hour clock with AM/PM column."
          },
          "showSeconds": {
            "type": "boolean",
            "default": "false",
            "description": "Include a seconds column."
          },
          "hourStep": {
            "type": "number",
            "default": "1",
            "description": "Step between available hour values."
          },
          "minuteStep": {
            "type": "number",
            "default": "1",
            "description": "Step between available minute values."
          },
          "secondStep": {
            "type": "number",
            "default": "1",
            "description": "Step between available second values."
          },
          "valueType": {
            "type": "'date' | 'string' | 'object'",
            "default": "'string'",
            "description": "Shape of the value passed to onChange."
          },
          "size": {
            "type": "'sm' | 'md' | 'lg'",
            "default": "'md'",
            "description": "Trigger size."
          },
          "variant": {
            "type": "'input' | 'inline'",
            "default": "'input'",
            "description": "Trigger style, or render the panel inline."
          },
          "disabled": {
            "type": "boolean",
            "default": "false",
            "description": "Disable interaction."
          },
          "readOnly": {
            "type": "boolean",
            "default": "false",
            "description": "Display-only mode."
          },
          "clearable": {
            "type": "boolean",
            "default": "true",
            "description": "Show a clear button when a value is set."
          },
          "placeholder": {
            "type": "string",
            "default": "'Select time'",
            "description": "Placeholder shown when empty."
          },
          "showNow": {
            "type": "boolean",
            "default": "true",
            "description": "Show the Now shortcut button."
          },
          "showConfirm": {
            "type": "boolean",
            "default": "false",
            "description": "Require an explicit OK click to commit."
          },
          "autoClose": {
            "type": "boolean",
            "description": "Close the popover immediately on selection. Defaults to the opposite of showConfirm."
          },
          "onChange": {
            "type": "(value: Date | string | TimeValue | null) => void",
            "description": "Called when the time changes."
          },
          "onOpenChange": {
            "type": "(open: boolean) => void",
            "description": "Called when the popover opens or closes."
          }
        }
      },
      "storyDir": "time-picker"
    },
    "Timeline": {
      "name": "Timeline",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "AlternateAlignment",
          "code": "import React from 'react';\nimport type { TimelineEvent } from '../../../components';\nimport { Timeline } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst events: TimelineEvent[] = [\n    {\n        id: '1',\n        title: 'Founded',\n        description: 'Company was founded in a small garage with a big dream.',\n        timestamp: '2018',\n        color: 'primary',\n    },\n    { id: '2', title: 'Series A Funding', description: 'Raised $5M in Series A to expand the team.', timestamp: '2019', color: 'success' },\n    { id: '3', title: 'Product Launch', description: 'Launched the flagship product to 10,000 users.', timestamp: '2020', color: 'info' },\n    {\n        id: '4',\n        title: 'Global Expansion',\n        description: 'Opened offices in 3 new countries across Europe and Asia.',\n        timestamp: '2021',\n        color: 'warning',\n    },\n    { id: '5', title: 'IPO', description: 'Went public on the NASDAQ stock exchange.', timestamp: '2023', color: 'danger' },\n    { id: '6', title: '1M Users', description: 'Reached one million active users worldwide.', timestamp: '2024', color: 'success' },\n];\n\nconst code = `import { Timeline } from 'fluxo-ui';\n\n<Timeline\n  events={events}\n  align=\"alternate\"\n  connectorStyle=\"dashed\"\n/>`;\n\nconst AlternateAlignment: React.FC = () => (\n    <>\n        <ComponentDemo\n            title=\"Alternate Alignment\"\n            description=\"Events alternate between left and right sides of the timeline axis.\"\n            centered={false}\n        >\n            <div className=\"w-full max-w-2xl mx-auto\">\n                <Timeline events={events} align=\"alternate\" connectorStyle=\"dashed\" />\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default AlternateAlignment;\n"
        },
        {
          "title": "BasicUsage",
          "code": "import React from 'react';\nimport type { TimelineEvent } from '../../../components';\nimport { Timeline } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst events: TimelineEvent[] = [\n    {\n        id: '1',\n        title: 'Order Placed',\n        description: 'Your order #12345 has been placed successfully.',\n        timestamp: 'Jan 15, 2025 - 9:00 AM',\n        color: 'primary',\n    },\n    {\n        id: '2',\n        title: 'Payment Confirmed',\n        description: 'Payment of $299.99 has been processed.',\n        timestamp: 'Jan 15, 2025 - 9:05 AM',\n        color: 'success',\n    },\n    {\n        id: '3',\n        title: 'Order Shipped',\n        description: 'Your package is on its way via Express Delivery.',\n        timestamp: 'Jan 16, 2025 - 2:30 PM',\n        color: 'info',\n    },\n    {\n        id: '4',\n        title: 'Out for Delivery',\n        description: 'The package is out for delivery in your area.',\n        timestamp: 'Jan 17, 2025 - 8:00 AM',\n        color: 'warning',\n    },\n    {\n        id: '5',\n        title: 'Delivered',\n        description: 'Your package has been delivered. Enjoy!',\n        timestamp: 'Jan 17, 2025 - 11:45 AM',\n        color: 'success',\n    },\n];\n\nconst code = `import { Timeline } from 'fluxo-ui';\nimport type { TimelineEvent } from 'fluxo-ui';\n\nconst events: TimelineEvent[] = [\n  { id: '1', title: 'Order Placed', description: 'Order #12345 placed.', timestamp: 'Jan 15', color: 'primary' },\n  { id: '2', title: 'Payment Confirmed', description: 'Payment processed.', timestamp: 'Jan 15', color: 'success' },\n  { id: '3', title: 'Shipped', description: 'Package on its way.', timestamp: 'Jan 16', color: 'info' },\n  { id: '4', title: 'Delivered', description: 'Package delivered.', timestamp: 'Jan 17', color: 'success' },\n];\n\n<Timeline events={events} />`;\n\nconst BasicUsage: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Order Tracking Timeline\" description=\"A vertical left-aligned timeline showing order progress.\">\n            <div className=\"w-full max-w-lg\">\n                <Timeline events={events} />\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default BasicUsage;\n"
        },
        {
          "title": "CustomMarkers",
          "code": "import React from 'react';\nimport type { TimelineEvent } from '../../../components';\nimport { Timeline } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst checkIcon = (\n    <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}>\n        <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M5 13l4 4L19 7\" />\n    </svg>\n);\n\nconst starIcon = (\n    <svg className=\"w-4 h-4\" fill=\"currentColor\" viewBox=\"0 0 24 24\">\n        <path d=\"M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z\" />\n    </svg>\n);\n\nconst rocketIcon = (\n    <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}>\n        <path\n            strokeLinecap=\"round\"\n            strokeLinejoin=\"round\"\n            d=\"M15.59 14.37a6 6 0 01-5.84 7.38v-4.8m5.84-2.58a14.98 14.98 0 006.16-12.12A14.98 14.98 0 009.63 8.41m5.96 5.96a14.926 14.926 0 01-5.841 2.58m-.119-8.54a6 6 0 00-7.381 5.84h4.8m2.581-5.84a14.927 14.927 0 00-2.58 5.841m2.699 2.7c-.103.021-.207.041-.311.06a15.09 15.09 0 01-2.448-2.448 14.9 14.9 0 01.06-.312m-2.24 2.39a4.493 4.493 0 00-1.757 4.306 4.493 4.493 0 004.306-1.758M16.5 9a1.5 1.5 0 11-3 0 1.5 1.5 0 013 0z\"\n        />\n    </svg>\n);\n\nconst events: TimelineEvent[] = [\n    { id: '1', title: 'Task Completed', description: 'Initial setup finished.', timestamp: '10:00 AM', icon: checkIcon, color: 'success' },\n    {\n        id: '2',\n        title: 'Achievement Unlocked',\n        description: 'First milestone reached!',\n        timestamp: '11:30 AM',\n        icon: starIcon,\n        color: 'warning',\n    },\n    {\n        id: '3',\n        title: 'Deployment',\n        description: 'Application deployed to production.',\n        timestamp: '2:00 PM',\n        icon: rocketIcon,\n        color: 'primary',\n    },\n    { id: '4', title: 'Review Done', description: 'Code review passed all checks.', timestamp: '3:45 PM', icon: checkIcon, color: 'info' },\n];\n\nconst code = `import { Timeline } from 'fluxo-ui';\n\nconst checkIcon = <svg>...</svg>;\n\nconst events = [\n  {\n    id: '1',\n    title: 'Task Completed',\n    icon: checkIcon,\n    color: 'success',\n  },\n  // ...\n];\n\n<Timeline\n  events={events}\n  markerSize=\"lg\"\n/>`;\n\nconst CustomMarkers: React.FC = () => (\n    <>\n        <ComponentDemo\n            title=\"Custom Icons & Markers\"\n            description=\"Use custom SVG icons in the timeline markers. Combine with markerSize for larger icons.\"\n        >\n            <div className=\"w-full max-w-lg\">\n                <Timeline events={events} markerSize=\"lg\" />\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default CustomMarkers;\n"
        },
        {
          "title": "HorizontalLayout",
          "code": "import React from 'react';\nimport type { TimelineEvent } from '../../../components';\nimport { Timeline } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst events: TimelineEvent[] = [\n    { id: '1', title: 'Research', timestamp: 'Week 1', color: 'primary' },\n    { id: '2', title: 'Design', timestamp: 'Week 2-3', color: 'info' },\n    { id: '3', title: 'Development', timestamp: 'Week 4-8', color: 'warning' },\n    { id: '4', title: 'Testing', timestamp: 'Week 9-10', color: 'danger' },\n    { id: '5', title: 'Launch', timestamp: 'Week 11', color: 'success' },\n];\n\nconst code = `import { Timeline } from 'fluxo-ui';\n\n<Timeline\n  events={events}\n  layout=\"horizontal\"\n/>`;\n\nconst HorizontalLayout: React.FC = () => (\n    <>\n        <ComponentDemo\n            title=\"Horizontal Timeline\"\n            description=\"A horizontal layout for project milestones or step-based workflows.\"\n            centered={false}\n        >\n            <div className=\"w-full overflow-x-auto\">\n                <Timeline events={events} layout=\"horizontal\" />\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default HorizontalLayout;\n"
        }
      ],
      "props": {
        "timelineProps": {
          "events": {
            "type": "TimelineEvent[]",
            "required": true,
            "description": "Array of timeline event data."
          },
          "layout": {
            "type": "'vertical' | 'horizontal'",
            "default": "'vertical'",
            "description": "Timeline orientation."
          },
          "align": {
            "type": "'left' | 'right' | 'alternate'",
            "default": "'left'",
            "description": "Content alignment relative to the timeline axis."
          },
          "connectorStyle": {
            "type": "'solid' | 'dashed' | 'dotted'",
            "default": "'solid'",
            "description": "Style of the connector lines between events."
          },
          "markerSize": {
            "type": "'sm' | 'md' | 'lg'",
            "default": "'md'",
            "description": "Size of timeline markers."
          },
          "className": {
            "type": "string",
            "description": "Additional CSS class for the container."
          },
          "headingLevel": {
            "type": "1 | 2 | 3 | 4 | 5 | 6",
            "default": "4",
            "description": "Heading level used for each event title (h1-h6)."
          },
          "ariaLabel": {
            "type": "string",
            "default": "'Timeline'",
            "description": "Accessible name for the timeline container."
          }
        },
        "eventProps": {
          "id": {
            "type": "string",
            "required": true,
            "description": "Unique identifier for the event."
          },
          "title": {
            "type": "string",
            "required": true,
            "description": "Event title text."
          },
          "description": {
            "type": "ReactNode",
            "description": "Event description or body content."
          },
          "timestamp": {
            "type": "string",
            "description": "Timestamp or date label."
          },
          "icon": {
            "type": "ReactNode",
            "description": "Custom icon displayed in the marker."
          },
          "color": {
            "type": "'primary' | 'success' | 'warning' | 'danger' | 'info'",
            "description": "Color theme for the marker."
          },
          "marker": {
            "type": "ReactNode",
            "description": "Fully custom marker element (overrides icon and dot)."
          },
          "content": {
            "type": "ReactNode",
            "description": "Additional custom content below description."
          },
          "href": {
            "type": "string",
            "description": "When set, renders the event content as a link to this URL."
          },
          "onClick": {
            "type": "() => void",
            "description": "When set, renders the event content as a button that fires this callback (mutually exclusive with href)."
          }
        }
      },
      "storyDir": "timeline"
    },
    "Tooltip": {
      "name": "Tooltip",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React from 'react';\nimport { Button, hideTooltip, showTooltip } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { showTooltip, hideTooltip } from 'fluxo-ui';\n\n<Button\n  onMouseEnter={(e) => showTooltip(e, 'Hello, I am a tooltip!')}\n  onMouseLeave={() => hideTooltip({ timeout: 0 })}\n>\n  Hover me\n</Button>`;\n\nconst BasicUsage: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo title=\"Simple string tooltip\">\n                <Button\n                    variant=\"primary\"\n                    onMouseEnter={(e) => showTooltip(e, 'Hello, I am a tooltip!')}\n                    onMouseLeave={() => hideTooltip({ timeout: 0 })}\n                >\n                    Hover me\n                </Button>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "CustomTimeout",
          "code": "import React from 'react';\nimport { Button, showTooltip, hideTooltip } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `// Instant hide\nshowTooltip(e, { content: 'Text', timeout: 0 });\nhideTooltip({ timeout: 0 });\n\n// Custom delay (ms)\nshowTooltip(e, { content: 'Text', timeout: 3000 });\nhideTooltip({ timeout: 3000 });\n\n// Default (1500ms)\nshowTooltip(e, { content: 'Text' });\nhideTooltip();`;\n\nconst CustomTimeout: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo\n                title=\"Tooltip with custom hide delay\"\n                description=\"The tooltip auto-hides after the configured timeout when the mouse leaves.\"\n            >\n                <div className=\"flex gap-4 flex-wrap\">\n                    <Button\n                        size=\"sm\"\n                        onMouseEnter={(e) => showTooltip(e, { content: 'Hides immediately on mouse leave', timeout: 0 })}\n                        onMouseLeave={() => hideTooltip({ timeout: 0 })}\n                    >\n                        Instant hide\n                    </Button>\n                    <Button\n                        size=\"sm\"\n                        variant=\"secondary\"\n                        onMouseEnter={(e) => showTooltip(e, { content: 'Stays for 3 seconds after mouse leave', timeout: 3000 })}\n                        onMouseLeave={() => hideTooltip({ timeout: 3000 })}\n                    >\n                        3 s delay\n                    </Button>\n                    <Button\n                        size=\"sm\"\n                        variant=\"info\"\n                        onMouseEnter={(e) => showTooltip(e, { content: 'Default: 1.5 s delay' })}\n                        onMouseLeave={() => hideTooltip()}\n                    >\n                        Default (1.5 s)\n                    </Button>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default CustomTimeout;\n"
        },
        {
          "title": "OnAnyElement",
          "code": "import cn from 'classnames';\nimport React from 'react';\nimport { showTooltip, hideTooltip } from '../../../components';\nimport { InfoIcon } from '../../../assets/icons';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\n\nconst code = `<span\n  onMouseEnter={(e) =>\n    showTooltip(e, {\n      content: 'Balance is updated every 24 hours.',\n      placement: 'topRight',\n    })\n  }\n  onMouseLeave={() => hideTooltip({ timeout: 0 })}\n>\n  <InfoIcon />\n</span>`;\n\nconst OnAnyElement: React.FC = () => {\n    const { isDark } = useStoryTheme();\n\n    return (\n        <>\n            <ComponentDemo title=\"Tooltip on any element\">\n                <div className=\"flex items-center gap-2\">\n                    <span className={cn('text-sm', { 'text-gray-300': isDark, 'text-gray-700': !isDark })}>Account balance</span>\n                    <span\n                        className=\"inline-flex items-center justify-center w-5 h-5 rounded-full bg-blue-600 text-white cursor-help\"\n                        onMouseEnter={(e) =>\n                            showTooltip(e, {\n                                content: 'Balance is updated every 24 hours. Contact support for discrepancies.',\n                                placement: 'topRight',\n                            })\n                        }\n                        onMouseLeave={() => hideTooltip({ timeout: 0 })}\n                    >\n                        <InfoIcon className=\"w-3 h-3\" />\n                    </span>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default OnAnyElement;\n"
        },
        {
          "title": "Placements",
          "code": "import React from 'react';\nimport { Button, showTooltip, hideTooltip } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst placements = ['topLeft', 'topRight', 'bottomLeft', 'bottomRight'] as const;\n\nconst code = `showTooltip(e, { content: 'Tooltip text', placement: 'topLeft' });\nshowTooltip(e, { content: 'Tooltip text', placement: 'topRight' });\nshowTooltip(e, { content: 'Tooltip text', placement: 'bottomLeft' });\nshowTooltip(e, { content: 'Tooltip text', placement: 'bottomRight' });\nshowTooltip(e, { content: 'Tooltip text', placement: 'auto' }); // default`;\n\nconst Placements: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo title=\"All placement options\" description=\"Hover each button to see the tooltip in that position.\">\n                <div className=\"flex flex-wrap gap-4 justify-center py-4\">\n                    {placements.map((placement) => (\n                        <Button\n                            key={placement}\n                            size=\"sm\"\n                            onMouseEnter={(e) =>\n                                showTooltip(e, { content: `Placement: ${placement}`, placement })\n                            }\n                            onMouseLeave={() => hideTooltip({ timeout: 0 })}\n                        >\n                            {placement}\n                        </Button>\n                    ))}\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default Placements;\n"
        },
        {
          "title": "RichContent",
          "code": "import React from 'react';\nimport { Button, showTooltip, hideTooltip } from '../../../components';\nimport { InfoIcon } from '../../../assets/icons';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `showTooltip(e, {\n  content: (\n    <div className=\"space-y-1\">\n      <p className=\"font-semibold text-sm\">Pro tip</p>\n      <p className=\"text-xs opacity-80\">\n        You can render any React node inside a tooltip.\n      </p>\n    </div>\n  ),\n  placement: 'bottomLeft',\n});`;\n\nconst RichContent: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo title=\"ReactNode as tooltip content\">\n                <Button\n                    variant=\"info\"\n                    layout=\"outlined\"\n                    leftIcon={<InfoIcon className=\"w-4 h-4\" />}\n                    onMouseEnter={(e) =>\n                        showTooltip(e, {\n                            content: (\n                                <div className=\"space-y-1\">\n                                    <p className=\"font-semibold text-sm\">Pro tip</p>\n                                    <p className=\"text-xs opacity-80\">You can render any React node inside a tooltip including lists, icons, and formatted text.</p>\n                                </div>\n                            ),\n                            placement: 'bottomLeft',\n                        })\n                    }\n                    onMouseLeave={() => hideTooltip({ timeout: 0 })}\n                >\n                    Rich Tooltip\n                </Button>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default RichContent;\n"
        },
        {
          "title": "SetupSection",
          "code": "import React from 'react';\nimport { CodeBlock } from '../../CodeBlock';\n\nconst code = `import { TooltipManager } from 'fluxo-ui';\n\nfunction App() {\n  return (\n    <>\n      <TooltipManager />\n      {/* rest of app */}\n    </>\n  );\n}`;\n\nconst SetupSection: React.FC = () => {\n    return <CodeBlock title=\"App root\" code={code} />;\n};\n\nexport default SetupSection;\n"
        }
      ],
      "props": {
        "tooltipProps": {
          "content": {
            "type": "React.ReactNode | string",
            "required": true,
            "description": "The content displayed inside the tooltip."
          },
          "placement": {
            "type": "'topLeft' | 'topRight' | 'bottomLeft' | 'bottomRight' | 'auto'",
            "default": "'auto'",
            "description": "Preferred placement relative to the target. 'auto' picks the best position based on available viewport space."
          },
          "timeout": {
            "type": "number",
            "default": "1500",
            "description": "Milliseconds before the tooltip auto-hides after the mouse leaves the target (0 = immediate)."
          }
        },
        "showTooltipProps": {
          "showTooltip(e, content)": {
            "type": "function",
            "description": "Show a tooltip anchored to the hovered element. Pass a string, ReactNode, or TooltipOptions object."
          },
          "hideTooltip({ timeout? })": {
            "type": "function",
            "description": "Explicitly hide the tooltip. Defaults to the configured timeout if not specified."
          }
        }
      },
      "storyDir": "tooltip"
    },
    "TouchRipple": {
      "name": "TouchRipple",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React from 'react';\nimport { TouchRipple } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { TouchRipple } from 'fluxo-ui';\n\n<TouchRipple as=\"button\" className=\"my-card\" onClick={onClick} role=\"button\" tabIndex={0}>\n    Tap me\n</TouchRipple>`;\n\nconst tileStyle: React.CSSProperties = {\n    appearance: 'none',\n    border: '1px solid var(--eui-border)',\n    background: 'var(--eui-bg)',\n    color: 'var(--eui-text)',\n    padding: '16px 24px',\n    borderRadius: 8,\n    fontSize: 14,\n    fontFamily: 'inherit',\n    cursor: 'pointer',\n    minWidth: 160,\n    textAlign: 'center',\n};\n\nconst BasicUsage: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Tap to ripple\" description=\"A Material-style ink ripple emits from the tap location and fades out.\">\n            <div style={{ display: 'flex', gap: 12, flexWrap: 'wrap' }}>\n                <TouchRipple as=\"button\" style={tileStyle} ariaLabel=\"Default ripple\">Tap me</TouchRipple>\n                <TouchRipple as=\"button\" style={tileStyle} center ariaLabel=\"Centered ripple\">Centered ripple</TouchRipple>\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\"><CodeBlock code={code} language=\"tsx\" /></div>\n    </>\n);\n\nexport default BasicUsage;\n"
        },
        {
          "title": "Variants",
          "code": "import React from 'react';\nimport { TouchRipple } from '../../../components';\nimport type { TouchRippleVariant } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<TouchRipple as=\"button\" variant=\"material\">Material</TouchRipple>\n<TouchRipple as=\"button\" variant=\"subtle\">Subtle</TouchRipple>\n<TouchRipple as=\"button\" variant=\"highlight\">Highlight</TouchRipple>\n<TouchRipple as=\"button\" variant=\"outline\">Outline</TouchRipple>`;\n\nconst tileStyle: React.CSSProperties = {\n    appearance: 'none',\n    border: '1px solid var(--eui-border)',\n    background: 'var(--eui-bg)',\n    color: 'var(--eui-text)',\n    padding: '16px 24px',\n    borderRadius: 8,\n    fontSize: 14,\n    fontFamily: 'inherit',\n    cursor: 'pointer',\n    minWidth: 160,\n    textAlign: 'center',\n};\n\nconst variants: { variant: TouchRippleVariant; label: string }[] = [\n    { variant: 'material', label: 'Material' },\n    { variant: 'subtle', label: 'Subtle' },\n    { variant: 'highlight', label: 'Highlight' },\n    { variant: 'outline', label: 'Outline' },\n];\n\nconst Variants: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Four ripple variants\" description=\"Material is the standard tap ink, Subtle is fainter, Highlight uses the primary color, Outline draws a focus ring on press/focus.\">\n            <div style={{ display: 'flex', gap: 12, flexWrap: 'wrap' }}>\n                {variants.map((v) => (\n                    <TouchRipple key={v.variant} as=\"button\" style={tileStyle} variant={v.variant} ariaLabel={v.label}>\n                        {v.label}\n                    </TouchRipple>\n                ))}\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\"><CodeBlock code={code} language=\"tsx\" /></div>\n    </>\n);\n\nexport default Variants;\n"
        }
      ],
      "props": {
        "touchRippleProps": {
          "children": {
            "type": "ReactNode",
            "required": true,
            "description": "Children rendered inside the ripple host."
          },
          "color": {
            "type": "string",
            "description": "Override the ripple color (defaults to currentColor)."
          },
          "center": {
            "type": "boolean",
            "default": "false",
            "description": "Always start the ripple at the center, regardless of tap location."
          },
          "duration": {
            "type": "number",
            "default": "500",
            "description": "Ripple animation duration in milliseconds."
          },
          "variant": {
            "type": "'material' | 'subtle' | 'highlight' | 'outline'",
            "default": "'material'",
            "description": "Visual style. 'material' is the standard tap ripple, 'subtle' is a faint variant, 'highlight' uses the primary color, 'outline' adds a focus ring on activation."
          },
          "disabled": {
            "type": "boolean",
            "default": "false",
            "description": "Disable ripple emission and pointer interaction."
          },
          "className": {
            "type": "string",
            "description": "Additional CSS class for the wrapper."
          },
          "as": {
            "type": "keyof JSX.IntrinsicElements",
            "default": "'div'",
            "description": "Element type to render. Use 'button' when used as a clickable surface."
          },
          "onClick": {
            "type": "(event: MouseEvent) => void",
            "description": "Forwarded click handler."
          },
          "role": {
            "type": "string",
            "description": "ARIA role for the host element."
          },
          "tabIndex": {
            "type": "number",
            "description": "Tab order index for keyboard navigation."
          },
          "ariaLabel": {
            "type": "string",
            "description": "Accessible name for the host element."
          },
          "style": {
            "type": "React.CSSProperties",
            "description": "Inline style passed through to the host element."
          }
        }
      },
      "storyDir": "touch-ripple"
    },
    "Tour": {
      "name": "Tour",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicTour",
          "code": "import cn from 'classnames';\nimport React, { useState } from 'react';\nimport { Button, StepTour } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\nimport { basicSteps } from './tour-story-data';\n\nconst code = `import { StepTour } from 'fluxo-ui';\nimport type { TourStep } from 'fluxo-ui/types';\n\nconst steps: TourStep[] = [\n  {\n    selector: '#dashboard-header',\n    title: 'Dashboard Overview',\n    content: 'This is your main dashboard with key metrics.',\n    placement: 'bottom',\n    order: 1,\n  },\n  {\n    selector: '#sidebar-nav',\n    title: 'Navigation',\n    content: 'Jump to any section from this sidebar.',\n    placement: 'right',\n    order: 2,\n  },\n];\n\nconst [isOpen, setIsOpen] = useState(false);\n\n<Button onClick={() => setIsOpen(true)}>Start Tour</Button>\n\n{isOpen && (\n  <StepTour\n    steps={steps}\n    isOpen={isOpen}\n    onClose={() => setIsOpen(false)}\n  />\n)}`;\n\nconst BasicTour: React.FC = () => {\n    const { isDark } = useStoryTheme();\n    const [basicOpen, setBasicOpen] = useState(false);\n\n    const mutedText = isDark ? 'text-gray-400' : 'text-gray-500';\n    const headingText = isDark ? 'text-gray-100' : 'text-gray-900';\n    const cardBg = isDark ? 'bg-gray-800/60 border border-gray-700' : 'bg-white border border-gray-200 shadow-sm';\n    const navBg = isDark ? 'bg-gray-800 border border-gray-700' : 'bg-gray-50 border border-gray-200';\n    const navActiveItem = isDark ? 'bg-blue-900/40 text-blue-300' : 'bg-blue-50 text-blue-700';\n    const navItem = isDark ? 'text-gray-400 hover:text-gray-200' : 'text-gray-600 hover:text-gray-800';\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Interactive dashboard tour\"\n                description=\"Click 'Start Tour' to walk through each highlighted element.\"\n                centered={false}\n            >\n                <div className=\"w-full space-y-4 p-2\">\n                    <div id=\"tour-dashboard-header\" className={`flex items-center justify-between px-4 py-3 rounded-lg ${cardBg}`}>\n                        <span className={cn('font-semibold text-sm', headingText)}>My Dashboard</span>\n                        <div id=\"tour-profile-menu\" className=\"flex items-center gap-2\">\n                            <div className=\"w-7 h-7 rounded-full bg-blue-500 flex items-center justify-center text-white text-xs font-bold\">\n                                JD\n                            </div>\n                            <span className={`text-xs ${mutedText}`}>John Doe</span>\n                        </div>\n                    </div>\n\n                    <div className=\"flex gap-4\">\n                        <div id=\"tour-nav-links\" className={`w-32 shrink-0 rounded-lg p-3 space-y-1 ${navBg}`}>\n                            {['Overview', 'Reports', 'Analytics', 'Settings'].map((item, i) => (\n                                <div\n                                    key={item}\n                                    className={`text-xs px-2 py-1.5 rounded cursor-pointer ${i === 0 ? navActiveItem : navItem}`}\n                                >\n                                    {item}\n                                </div>\n                            ))}\n                        </div>\n\n                        <div className=\"flex-1 space-y-4\">\n                            <div id=\"tour-stats-panel\" className=\"grid grid-cols-1 sm:grid-cols-3 gap-3\">\n                                {[\n                                    { label: 'Users', value: '14,209', delta: '+8%' },\n                                    { label: 'Revenue', value: '$98.4k', delta: '+12%' },\n                                    { label: 'Orders', value: '3,741', delta: '+5%' },\n                                ].map(({ label, value, delta }) => (\n                                    <div key={label} className={`rounded-lg p-3 ${cardBg}`}>\n                                        <div className={`text-xs ${mutedText}`}>{label}</div>\n                                        <div className={cn('text-base font-bold', headingText)}>{value}</div>\n                                        <div className=\"text-xs text-green-500\">{delta}</div>\n                                    </div>\n                                ))}\n                            </div>\n\n                            <div className=\"flex items-center gap-2 flex-wrap\">\n                                <div id=\"tour-action-bar\" className=\"flex items-center gap-2\">\n                                    <Button variant=\"primary\" size=\"sm\">\n                                        New Report\n                                    </Button>\n                                    <Button variant=\"secondary\" layout=\"outlined\" size=\"sm\">\n                                        Export\n                                    </Button>\n                                    <Button variant=\"secondary\" layout=\"outlined\" size=\"sm\">\n                                        Filter\n                                    </Button>\n                                </div>\n                                <div className=\"ml-auto\">\n                                    <Button variant=\"primary\" layout=\"outlined\" size=\"sm\" onClick={() => setBasicOpen(true)}>\n                                        Start Tour\n                                    </Button>\n                                </div>\n                            </div>\n                        </div>\n                    </div>\n                </div>\n\n                {basicOpen && <StepTour steps={basicSteps} isOpen={basicOpen} onClose={() => setBasicOpen(false)} />}\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default BasicTour;\n"
        },
        {
          "title": "DarkModeSection",
          "code": "import React from 'react';\nimport { useStoryTheme } from '../../StoryThemeContext';\n\nconst DarkModeSection: React.FC = () => {\n    const { isDark } = useStoryTheme();\n\n    const mutedText = isDark ? 'text-gray-400' : 'text-gray-500';\n    const headingText = isDark ? 'text-gray-100' : 'text-gray-900';\n\n    return (\n        <div className={`rounded-xl border p-5 space-y-3 ${isDark ? 'border-white/8 bg-[#0d0f14]' : 'border-gray-200 bg-white'}`}>\n            <div className=\"flex gap-6 text-sm flex-wrap\">\n                <div className=\"space-y-1\">\n                    <div className={`text-xs font-medium ${mutedText}`}>Light mode</div>\n                    <div className=\"flex items-center gap-2\">\n                        <div className=\"w-5 h-5 rounded border border-gray-200 bg-white shadow-sm\" />\n                        <span className={headingText}>Tooltip background</span>\n                    </div>\n                    <div className=\"flex items-center gap-2\">\n                        <div className=\"w-5 h-5 rounded bg-black opacity-80\" />\n                        <span className={headingText}>Overlay (80% black)</span>\n                    </div>\n                    <div className=\"flex items-center gap-2\">\n                        <div className=\"w-5 h-5 rounded border-2 border-dashed border-yellow-500\" />\n                        <span className={headingText}>Highlight border</span>\n                    </div>\n                </div>\n                <div className=\"space-y-1\">\n                    <div className={`text-xs font-medium ${mutedText}`}>Dark mode</div>\n                    <div className=\"flex items-center gap-2\">\n                        <div className=\"w-5 h-5 rounded border border-gray-600 bg-gray-800\" />\n                        <span className={headingText}>Tooltip background</span>\n                    </div>\n                    <div className=\"flex items-center gap-2\">\n                        <div className=\"w-5 h-5 rounded bg-gray-500 opacity-60\" />\n                        <span className={headingText}>Overlay (60% gray)</span>\n                    </div>\n                    <div className=\"flex items-center gap-2\">\n                        <div className=\"w-5 h-5 rounded border-2 border-dashed border-yellow-300\" />\n                        <span className={headingText}>Highlight border</span>\n                    </div>\n                </div>\n            </div>\n        </div>\n    );\n};\n\nexport default DarkModeSection;\n"
        },
        {
          "title": "PlacementOptions",
          "code": "import cn from 'classnames';\nimport React, { useState } from 'react';\nimport { Button, StepTour } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\nimport { placementSteps } from './tour-story-data';\n\nconst code = `const steps: TourStep[] = [\n  { selector: '#el-top',    title: 'Top',    content: '...', placement: 'top'    },\n  { selector: '#el-bottom', title: 'Bottom', content: '...', placement: 'bottom' },\n  { selector: '#el-left',   title: 'Left',   content: '...', placement: 'left'   },\n  { selector: '#el-right',  title: 'Right',  content: '...', placement: 'right'  },\n];\n\n// The tooltip falls back gracefully when the viewport has insufficient space.`;\n\nconst PlacementOptions: React.FC = () => {\n    const { isDark } = useStoryTheme();\n    const [placementOpen, setPlacementOpen] = useState(false);\n\n    const headingText = isDark ? 'text-gray-100' : 'text-gray-900';\n    const cardBg = isDark ? 'bg-gray-800/60 border border-gray-700' : 'bg-white border border-gray-200 shadow-sm';\n    const tagBg = isDark ? 'bg-gray-700 text-gray-300' : 'bg-gray-100 text-gray-700';\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Tooltip placements — top · bottom · left · right\"\n                description=\"Tour through the four placement variants. Watch the tooltip anchor to each side.\"\n                centered={false}\n            >\n                <div className=\"w-full p-4\">\n                    <div className=\"grid grid-cols-3 gap-4 place-items-center\">\n                        <div />\n                        <div id=\"placement-top\" className={cn(`px-4 py-2 rounded-lg text-sm font-medium text-center ${cardBg}`, headingText)}>Top</div>\n                        <div />\n\n                        <div id=\"placement-left\" className={cn(`px-4 py-2 rounded-lg text-sm font-medium text-center ${cardBg}`, headingText)}>Left</div>\n                        <div className={`w-16 h-16 rounded-full flex items-center justify-center ${tagBg} text-xl`}>🎯</div>\n                        <div id=\"placement-right\" className={cn(`px-4 py-2 rounded-lg text-sm font-medium text-center ${cardBg}`, headingText)}>Right</div>\n\n                        <div />\n                        <div id=\"placement-bottom\" className={cn(`px-4 py-2 rounded-lg text-sm font-medium text-center ${cardBg}`, headingText)}>Bottom</div>\n                        <div />\n                    </div>\n\n                    <div className=\"mt-4 flex justify-end\">\n                        <Button variant=\"primary\" layout=\"outlined\" size=\"sm\" onClick={() => setPlacementOpen(true)}>\n                            Start Placement Tour\n                        </Button>\n                    </div>\n                </div>\n\n                {placementOpen && (\n                    <StepTour steps={placementSteps} isOpen={placementOpen} onClose={() => setPlacementOpen(false)} />\n                )}\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default PlacementOptions;\n"
        },
        {
          "title": "RichContent",
          "code": "import cn from 'classnames';\nimport React, { useMemo, useState } from 'react';\nimport { Button, StepTour } from '../../../components';\nimport { TourStep } from '../../../components/tour/types';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\n\nconst code = `const steps: TourStep[] = [\n  {\n    selector: '#export-button',\n    title: '🚀 New Feature',\n    content: (\n      <div className=\"space-y-2 text-sm\">\n        <p>This powerful feature lets you:</p>\n        <ul className=\"list-disc list-inside space-y-1 text-gray-500\">\n          <li>Export data in multiple formats</li>\n          <li>Schedule automated reports</li>\n        </ul>\n      </div>\n    ),\n    placement: 'bottom',\n  },\n  {\n    selector: '#config-panel',\n    title: '⚙️ Configuration',\n    content: (\n      <div className=\"space-y-2 text-sm\">\n        <p>Configure this panel to match your workflow.</p>\n        <div className=\"p-2 rounded bg-yellow-50 text-yellow-800 text-xs\">\n          Tip: Changes are saved automatically.\n        </div>\n      </div>\n    ),\n    placement: 'right',\n  },\n];`;\n\nconst RichContent: React.FC = () => {\n    const { isDark } = useStoryTheme();\n    const [richOpen, setRichOpen] = useState(false);\n\n    const mutedText = isDark ? 'text-gray-400' : 'text-gray-500';\n    const headingText = isDark ? 'text-gray-100' : 'text-gray-900';\n    const cardBg = isDark ? 'bg-gray-800/60 border border-gray-700' : 'bg-white border border-gray-200 shadow-sm';\n    const listItemText = isDark ? 'text-gray-400' : 'text-gray-600';\n    const tipBox = isDark ? 'bg-yellow-900/30 text-yellow-300' : 'bg-yellow-50 text-yellow-800';\n    const statusText = isDark ? 'text-green-400' : 'text-green-700';\n\n    const richContentSteps: TourStep[] = useMemo(() => [\n        {\n            selector: '#rich-feature-a',\n            title: '🚀 New Feature',\n            content: (\n                <div className=\"space-y-2 text-sm\">\n                    <p>This powerful feature lets you:</p>\n                    <ul className={`list-disc list-inside space-y-1 ${listItemText}`}>\n                        <li>Export data in multiple formats</li>\n                        <li>Schedule automated reports</li>\n                        <li>Share with your team instantly</li>\n                    </ul>\n                </div>\n            ),\n            placement: 'bottom',\n        },\n        {\n            selector: '#rich-feature-b',\n            title: '⚙️ Configuration',\n            content: (\n                <div className=\"space-y-2 text-sm\">\n                    <p>Configure this panel to match your workflow.</p>\n                    <div className={`mt-2 p-2 rounded text-xs ${tipBox}`}>\n                        Tip: Changes are saved automatically.\n                    </div>\n                </div>\n            ),\n            placement: 'right',\n        },\n        {\n            selector: '#rich-feature-c',\n            title: \"✅ You're Ready\",\n            content: (\n                <div className=\"space-y-2 text-sm\">\n                    <p>You have completed setup. Your workspace is ready to use.</p>\n                    <div className=\"flex items-center gap-2 mt-1\">\n                        <span className=\"w-2 h-2 rounded-full bg-green-500 inline-block\" />\n                        <span className={`font-medium ${statusText}`}>All systems operational</span>\n                    </div>\n                </div>\n            ),\n            placement: 'top',\n        },\n    ], [listItemText, tipBox, statusText]);\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Steps with rich JSX content\"\n                description=\"Tour steps can contain lists, callouts, icons, and styled elements.\"\n                centered={false}\n            >\n                <div className=\"w-full space-y-3 p-2\">\n                    <div className=\"flex items-center gap-3 flex-wrap\">\n                        <div id=\"rich-feature-a\" className={`flex items-center gap-2 px-4 py-2.5 rounded-lg ${cardBg}`}>\n                            <span className=\"text-lg\">📤</span>\n                            <div>\n                                <div className={cn('text-sm font-medium', headingText)}>Export</div>\n                                <div className={`text-xs ${mutedText}`}>Multi-format export</div>\n                            </div>\n                        </div>\n\n                        <div id=\"rich-feature-b\" className={`flex items-center gap-2 px-4 py-2.5 rounded-lg ${cardBg}`}>\n                            <span className=\"text-lg\">⚙️</span>\n                            <div>\n                                <div className={cn('text-sm font-medium', headingText)}>Configure</div>\n                                <div className={`text-xs ${mutedText}`}>Auto-saved settings</div>\n                            </div>\n                        </div>\n\n                        <div id=\"rich-feature-c\" className={`flex items-center gap-2 px-4 py-2.5 rounded-lg ${cardBg}`}>\n                            <span className=\"text-lg\">✅</span>\n                            <div>\n                                <div className={cn('text-sm font-medium', headingText)}>Status</div>\n                                <div className=\"text-xs text-green-500\">All systems go</div>\n                            </div>\n                        </div>\n\n                        <div className=\"ml-auto\">\n                            <Button variant=\"primary\" layout=\"outlined\" size=\"sm\" onClick={() => setRichOpen(true)}>\n                                Start Tour\n                            </Button>\n                        </div>\n                    </div>\n                </div>\n\n                {richOpen && (\n                    <StepTour steps={richContentSteps} isOpen={richOpen} onClose={() => setRichOpen(false)} />\n                )}\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default RichContent;\n"
        },
        {
          "title": "StartAtStep",
          "code": "import cn from 'classnames';\nimport React, { useState } from 'react';\nimport { Button, StepTour } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\nimport { startAtSteps } from './tour-story-data';\n\nconst code = `const steps: TourStep[] = [\n  { selector: '#header',    title: 'Dashboard Overview', content: '...', placement: 'bottom' },\n  { selector: '#stats',     title: 'Key Metrics',        content: '...', placement: 'bottom' },\n  { selector: '#actions',   title: 'Quick Actions',      content: '...', placement: 'top'    },\n  { selector: '#sidebar',   title: 'Navigation',         content: '...', placement: 'right'  },\n  { selector: '#profile',   title: 'Your Profile',       content: '...', placement: 'left'   },\n];\n\n// Restore progress from storage\nconst savedStep = parseInt(localStorage.getItem('tour-step') ?? '0', 10);\n\n{isOpen && (\n  <StepTour\n    steps={steps}\n    isOpen={isOpen}\n    onClose={() => setIsOpen(false)}\n    initialStep={savedStep}\n  />\n)}`;\n\nconst StartAtStep: React.FC = () => {\n    const { isDark } = useStoryTheme();\n    const [startAtOpen, setStartAtOpen] = useState(false);\n    const [startAtIndex, setStartAtIndex] = useState(2);\n\n    const mutedText = isDark ? 'text-gray-400' : 'text-gray-500';\n    const headingText = isDark ? 'text-gray-100' : 'text-gray-900';\n    const cardBg = isDark ? 'bg-gray-800/60 border border-gray-700' : 'bg-white border border-gray-200 shadow-sm';\n    const navBg = isDark ? 'bg-gray-800 border border-gray-700' : 'bg-gray-50 border border-gray-200';\n    const navActiveItem = isDark ? 'bg-blue-900/40 text-blue-300' : 'bg-blue-50 text-blue-700';\n    const navItem = isDark ? 'text-gray-400 hover:text-gray-200' : 'text-gray-600 hover:text-gray-800';\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Resuming from an arbitrary step\"\n                description=\"Choose a starting step index (0-based) then launch the tour.\"\n                centered={false}\n            >\n                <div className=\"w-full space-y-4 p-2\">\n                    <div id=\"startat-step-a\" className={`flex items-center justify-between px-4 py-3 rounded-lg ${cardBg}`}>\n                        <span className={cn('font-semibold text-sm', headingText)}>My Dashboard</span>\n                        <div id=\"startat-step-e\" className=\"flex items-center gap-2\">\n                            <div className=\"w-7 h-7 rounded-full bg-blue-500 flex items-center justify-center text-white text-xs font-bold\">JD</div>\n                            <span className={`text-xs ${mutedText}`}>John Doe</span>\n                        </div>\n                    </div>\n\n                    <div className=\"flex gap-4\">\n                        <div id=\"startat-step-d\" className={`w-32 shrink-0 rounded-lg p-3 space-y-1 ${navBg}`}>\n                            {['Overview', 'Reports', 'Analytics', 'Settings'].map((item, i) => (\n                                <div key={item} className={`text-xs px-2 py-1.5 rounded cursor-pointer ${i === 0 ? navActiveItem : navItem}`}>{item}</div>\n                            ))}\n                        </div>\n\n                        <div className=\"flex-1 space-y-4\">\n                            <div id=\"startat-step-b\" className=\"grid grid-cols-1 sm:grid-cols-3 gap-3\">\n                                {[\n                                    { label: 'Users', value: '14,209', delta: '+8%' },\n                                    { label: 'Revenue', value: '$98.4k', delta: '+12%' },\n                                    { label: 'Orders', value: '3,741', delta: '+5%' },\n                                ].map(({ label, value, delta }) => (\n                                    <div key={label} className={`rounded-lg p-3 ${cardBg}`}>\n                                        <div className={`text-xs ${mutedText}`}>{label}</div>\n                                        <div className={cn('text-base font-bold', headingText)}>{value}</div>\n                                        <div className=\"text-xs text-green-500\">{delta}</div>\n                                    </div>\n                                ))}\n                            </div>\n\n                            <div className=\"flex items-center gap-2 flex-wrap\">\n                                <div id=\"startat-step-c\" className=\"flex items-center gap-2\">\n                                    <Button variant=\"primary\" size=\"sm\">New Report</Button>\n                                    <Button variant=\"secondary\" layout=\"outlined\" size=\"sm\">Export</Button>\n                                    <Button variant=\"secondary\" layout=\"outlined\" size=\"sm\">Filter</Button>\n                                </div>\n                            </div>\n                        </div>\n                    </div>\n\n                    <div className=\"flex items-center gap-2 flex-wrap\">\n                        {startAtSteps.map((_s, i) => (\n                            <button\n                                key={i}\n                                type=\"button\"\n                                onClick={() => setStartAtIndex(i)}\n                                className={`px-3 py-1 rounded-full text-xs font-medium border transition-colors ${\n                                    startAtIndex === i\n                                        ? 'bg-blue-500 border-blue-500 text-white'\n                                        : isDark\n                                        ? 'border-gray-600 text-gray-400 hover:border-gray-400'\n                                        : 'border-gray-300 text-gray-500 hover:border-gray-400'\n                                }`}\n                            >\n                                Step {i + 1}\n                            </button>\n                        ))}\n                    </div>\n\n                    <div className={`rounded-lg px-4 py-3 text-sm ${cardBg}`}>\n                        <span className={mutedText}>Starting from: </span>\n                        <span className={cn('font-medium', headingText)}>\n                            {startAtSteps[startAtIndex]?.title ?? `Step ${startAtIndex + 1}`}\n                        </span>\n                        <span className={` ml-2 text-xs ${mutedText}`}>(index {startAtIndex})</span>\n                    </div>\n\n                    <div className=\"flex justify-end\">\n                        <Button variant=\"primary\" layout=\"outlined\" size=\"sm\" onClick={() => setStartAtOpen(true)}>\n                            Start from Step {startAtIndex + 1}\n                        </Button>\n                    </div>\n                </div>\n\n                {startAtOpen && (\n                    <StepTour\n                        steps={startAtSteps}\n                        isOpen={startAtOpen}\n                        onClose={() => setStartAtOpen(false)}\n                        initialStep={startAtIndex}\n                    />\n                )}\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default StartAtStep;\n"
        },
        {
          "title": "StepCallbacks",
          "code": "import React, { useMemo, useState } from 'react';\nimport { Button, StepTour } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\nimport { callbackSteps, darkEventColor, lightEventColor, eventLabel } from './tour-story-data';\nimport type { LogEntry } from './tour-story-data';\n\nconst code = `const steps: TourStep[] = [\n  {\n    selector: '#feature-a',\n    title: 'Feature A',\n    content: 'This is Feature A.',\n    onNext: () => analytics.track('tour_step_next', { step: 1 }),\n    onSkip: () => analytics.track('tour_skip', { step: 1 }),\n  },\n  {\n    selector: '#feature-b',\n    title: 'Feature B',\n    content: 'This is Feature B.',\n    onPrev: () => analytics.track('tour_step_prev', { step: 2 }),\n    onNext: () => analytics.track('tour_step_next', { step: 2 }),\n  },\n];`;\n\nconst StepCallbacks: React.FC = () => {\n    const { isDark } = useStoryTheme();\n    const [cbOpen, setCbOpen] = useState(false);\n    const [log, setLog] = useState<LogEntry[]>([]);\n\n    const mutedText = isDark ? 'text-gray-400' : 'text-gray-500';\n    const tagBg = isDark ? 'bg-gray-700 text-gray-300' : 'bg-gray-100 text-gray-700';\n    const logBg = isDark ? 'bg-gray-900 border border-gray-700' : 'bg-gray-50 border border-gray-200';\n    const eventColor = isDark ? darkEventColor : lightEventColor;\n\n    const addLog = (step: number, event: LogEntry['event']) => {\n        const time = new Date().toLocaleTimeString('en-US', { hour12: false });\n        setLog((prev) => [{ step, event, time }, ...prev].slice(0, 20));\n    };\n\n    const trackedCallbackSteps = useMemo(() => callbackSteps.map((s, i) => ({\n        ...s,\n        onNext: () => setLog((prev) => [{ step: i + 1, event: 'next' as const, time: new Date().toLocaleTimeString('en-US', { hour12: false }) }, ...prev].slice(0, 20)),\n        onPrev: () => setLog((prev) => [{ step: i + 1, event: 'prev' as const, time: new Date().toLocaleTimeString('en-US', { hour12: false }) }, ...prev].slice(0, 20)),\n        onSkip: () => setLog((prev) => [{ step: i + 1, event: 'skip' as const, time: new Date().toLocaleTimeString('en-US', { hour12: false }) }, ...prev].slice(0, 20)),\n    })), []);\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Per-step lifecycle callbacks\"\n                description=\"Start the tour and navigate between steps — live events appear in the log below.\"\n                centered={false}\n            >\n                <div className=\"w-full space-y-4 p-2\">\n                    <div className=\"flex items-center gap-4 flex-wrap\">\n                        <span id=\"cb-step-1\" className={`px-3 py-1.5 rounded-full text-xs font-medium ${tagBg}`}>Step 1</span>\n                        <span id=\"cb-step-2\" className={`px-3 py-1.5 rounded-full text-xs font-medium ${tagBg}`}>Step 2</span>\n                        <span id=\"cb-step-3\" className={`px-3 py-1.5 rounded-full text-xs font-medium ${tagBg}`}>Step 3</span>\n                        <div className=\"ml-auto flex items-center gap-2\">\n                            {log.length > 0 && (\n                                <button\n                                    className={`text-xs ${mutedText} hover:${isDark ? 'text-gray-200' : 'text-gray-800'}`}\n                                    onClick={() => setLog([])}\n                                    type=\"button\"\n                                >\n                                    Clear log\n                                </button>\n                            )}\n                            <Button\n                                variant=\"primary\"\n                                layout=\"outlined\"\n                                size=\"sm\"\n                                onClick={() => {\n                                    setLog([]);\n                                    setCbOpen(true);\n                                }}\n                            >\n                                Start Tour\n                            </Button>\n                        </div>\n                    </div>\n\n                    <div className={`rounded-lg p-3 min-h-24 font-mono text-xs overflow-y-auto max-h-36 ${logBg}`}>\n                        {log.length === 0 ? (\n                            <span className={mutedText}>No events yet. Start the tour to see callbacks fire.</span>\n                        ) : (\n                            log.map((entry, i) => (\n                                <div key={i} className=\"flex items-center gap-2 py-0.5\">\n                                    <span className={mutedText}>{entry.time}</span>\n                                    <span className={`font-semibold ${eventColor[entry.event]}`}>\n                                        {eventLabel[entry.event]}\n                                    </span>\n                                    <span className={mutedText}>— step {entry.step}</span>\n                                </div>\n                            ))\n                        )}\n                    </div>\n                </div>\n\n                {cbOpen && (\n                    <StepTour\n                        steps={trackedCallbackSteps}\n                        isOpen={cbOpen}\n                        onClose={() => {\n                            addLog(trackedCallbackSteps.length, 'done');\n                            setCbOpen(false);\n                        }}\n                    />\n                )}\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} />\n            </div>\n        </>\n    );\n};\n\nexport default StepCallbacks;\n"
        }
      ],
      "props": {
        "tourProps": {
          "steps": {
            "type": "TourStep[]",
            "required": true,
            "description": "Ordered list of tour steps. Each step targets a DOM element via a CSS selector."
          },
          "isOpen": {
            "type": "boolean",
            "required": true,
            "description": "Controls whether the tour is visible."
          },
          "onClose": {
            "type": "() => void",
            "required": true,
            "description": "Called when the user skips or completes the tour."
          },
          "initialStep": {
            "type": "number",
            "default": "0",
            "description": "Zero-based index of the step to start from."
          },
          "zIndex": {
            "type": "number",
            "default": "10050",
            "description": "Base z-index for the tour overlay, highlight, and tooltip layers. Defaults above modals/drawers per popover rules."
          },
          "ariaLabel": {
            "type": "string",
            "default": "'Product tour'",
            "description": "Accessible name for the tour dialog read by screen readers."
          },
          "interactiveHighlight": {
            "type": "boolean",
            "default": "false",
            "description": "When true, clicks pass through the highlight overlay so users can interact with the highlighted element during the tour."
          },
          "onMissingStep": {
            "type": "(stepIndex: number, step: TourStep) => void",
            "description": "Called when a step's selector does not match any element so consumers can advance, retry, or surface the issue."
          }
        },
        "stepProps": {
          "selector": {
            "type": "string",
            "required": true,
            "description": "CSS selector that identifies the target DOM element for this step."
          },
          "title": {
            "type": "ReactNode",
            "description": "Optional heading shown at the top of the tooltip."
          },
          "content": {
            "type": "ReactNode",
            "required": true,
            "description": "Body content of the step tooltip. Supports JSX."
          },
          "placement": {
            "type": "'top' | 'bottom' | 'left' | 'right'",
            "default": "'bottom'",
            "description": "Preferred side for the tooltip relative to the target element. Falls back automatically if there is not enough space."
          },
          "order": {
            "type": "number",
            "description": "Explicit sort order for this step (defaults to array index position)."
          },
          "onNext": {
            "type": "() => void",
            "description": "Callback fired when the user advances past this step."
          },
          "onPrev": {
            "type": "() => void",
            "description": "Callback fired when the user goes back to this step."
          },
          "onSkip": {
            "type": "() => void",
            "description": "Callback fired when the user skips the tour from this step."
          }
        }
      },
      "storyDir": "tour"
    },
    "TreeView": {
      "name": "TreeView",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "AsyncLoading",
          "code": "import React from 'react';\nimport type { TreeNode } from '../../../components';\nimport { TreeView } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst nodes: TreeNode[] = [\n    { id: 'node-1', label: 'Lazy Folder A' },\n    { id: 'node-2', label: 'Lazy Folder B' },\n    { id: 'node-3', label: 'Lazy Folder C' },\n    { id: 'leaf-1', label: 'Static File.txt', isLeaf: true },\n];\n\nconst loadChildren = (node: TreeNode): Promise<TreeNode[]> => {\n    return new Promise((resolve) => {\n        setTimeout(() => {\n            resolve([\n                { id: `${node.id}-child-1`, label: `${node.label} - Child 1`, isLeaf: true },\n                { id: `${node.id}-child-2`, label: `${node.label} - Child 2`, isLeaf: true },\n                { id: `${node.id}-sub`, label: `${node.label} - Subfolder` },\n            ]);\n        }, 1200);\n    });\n};\n\nconst code = `import { TreeView } from 'fluxo-ui';\nimport type { TreeNode } from 'fluxo-ui';\n\nconst loadChildren = (node: TreeNode): Promise<TreeNode[]> => {\n  return new Promise((resolve) => {\n    setTimeout(() => {\n      resolve([\n        { id: \\`\\${node.id}-child-1\\`, label: 'Child 1', isLeaf: true },\n        { id: \\`\\${node.id}-child-2\\`, label: 'Child 2', isLeaf: true },\n        { id: \\`\\${node.id}-sub\\`, label: 'Subfolder' },\n      ]);\n    }, 1200);\n  });\n};\n\n<TreeView\n  nodes={nodes}\n  loadChildren={loadChildren}\n/>`;\n\nconst AsyncLoading: React.FC = () => (\n    <>\n        <ComponentDemo\n            title=\"Async Loading\"\n            description=\"Nodes load their children lazily when expanded. A spinner is shown during loading.\"\n        >\n            <div className=\"w-full max-w-sm\">\n                <TreeView nodes={nodes} loadChildren={loadChildren} />\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default AsyncLoading;\n"
        },
        {
          "title": "BasicUsage",
          "code": "import React from 'react';\nimport type { TreeNode } from '../../../components';\nimport { TreeView } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst nodes: TreeNode[] = [\n    {\n        id: 'docs',\n        label: 'Documents',\n        children: [\n            {\n                id: 'work',\n                label: 'Work',\n                children: [\n                    { id: 'resume', label: 'Resume.pdf', isLeaf: true },\n                    { id: 'cover', label: 'CoverLetter.docx', isLeaf: true },\n                ],\n            },\n            {\n                id: 'personal',\n                label: 'Personal',\n                children: [\n                    { id: 'taxes', label: 'Taxes_2024.pdf', isLeaf: true },\n                    { id: 'notes', label: 'Notes.txt', isLeaf: true },\n                ],\n            },\n        ],\n    },\n    {\n        id: 'photos',\n        label: 'Photos',\n        children: [\n            { id: 'vacation', label: 'Vacation.jpg', isLeaf: true },\n            { id: 'family', label: 'Family.png', isLeaf: true },\n        ],\n    },\n    {\n        id: 'music',\n        label: 'Music',\n        children: [\n            { id: 'track1', label: 'Song1.mp3', isLeaf: true },\n            { id: 'track2', label: 'Song2.mp3', isLeaf: true },\n        ],\n    },\n];\n\nconst code = `import { TreeView } from 'fluxo-ui';\nimport type { TreeNode } from 'fluxo-ui';\n\nconst nodes: TreeNode[] = [\n  {\n    id: 'docs',\n    label: 'Documents',\n    children: [\n      {\n        id: 'work',\n        label: 'Work',\n        children: [\n          { id: 'resume', label: 'Resume.pdf', isLeaf: true },\n          { id: 'cover', label: 'CoverLetter.docx', isLeaf: true },\n        ],\n      },\n    ],\n  },\n  {\n    id: 'photos',\n    label: 'Photos',\n    children: [\n      { id: 'vacation', label: 'Vacation.jpg', isLeaf: true },\n    ],\n  },\n];\n\n<TreeView\n  nodes={nodes}\n  defaultExpandedKeys={new Set(['docs'])}\n  onSelect={(keys, node) => console.log('Selected:', node.label)}\n/>`;\n\nconst BasicUsage: React.FC = () => (\n    <>\n        <ComponentDemo title=\"File Explorer Tree\" description=\"A basic tree view with expandable folders and selectable nodes.\">\n            <div className=\"w-full max-w-sm\">\n                <TreeView\n                    nodes={nodes}\n                    defaultExpandedKeys={new Set(['docs'])}\n                    onSelect={(_keys, node) => console.log('Selected:', node.label)}\n                />\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default BasicUsage;\n"
        },
        {
          "title": "CheckboxMode",
          "code": "import React, { useState } from 'react';\nimport type { TreeNode } from '../../../components';\nimport { TreeView } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst nodes: TreeNode[] = [\n    {\n        id: 'permissions',\n        label: 'Permissions',\n        children: [\n            {\n                id: 'users',\n                label: 'User Management',\n                children: [\n                    { id: 'user-view', label: 'View Users', isLeaf: true },\n                    { id: 'user-create', label: 'Create Users', isLeaf: true },\n                    { id: 'user-edit', label: 'Edit Users', isLeaf: true },\n                    { id: 'user-delete', label: 'Delete Users', isLeaf: true },\n                ],\n            },\n            {\n                id: 'roles',\n                label: 'Role Management',\n                children: [\n                    { id: 'role-view', label: 'View Roles', isLeaf: true },\n                    { id: 'role-create', label: 'Create Roles', isLeaf: true },\n                    { id: 'role-edit', label: 'Edit Roles', isLeaf: true },\n                ],\n            },\n            {\n                id: 'settings',\n                label: 'Settings',\n                children: [\n                    { id: 'settings-view', label: 'View Settings', isLeaf: true },\n                    { id: 'settings-edit', label: 'Edit Settings', isLeaf: true },\n                ],\n            },\n        ],\n    },\n];\n\nconst code = `import { TreeView } from 'fluxo-ui';\nimport type { TreeNode } from 'fluxo-ui';\n\n<TreeView\n  nodes={nodes}\n  checkboxes\n  defaultExpandedKeys={new Set(['permissions', 'users'])}\n  onCheck={(keys, node) => console.log('Checked:', [...keys])}\n/>`;\n\nconst CheckboxMode: React.FC = () => {\n    const [checkedKeys, setCheckedKeys] = useState<Set<string>>(new Set(['user-view', 'user-create']));\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Checkbox Tree\"\n                description=\"Tree with tri-state checkboxes for permission management. Parent nodes show indeterminate state when partially checked.\"\n            >\n                <div className=\"w-full max-w-sm\">\n                    <TreeView\n                        nodes={nodes}\n                        checkboxes\n                        checkedKeys={checkedKeys}\n                        defaultExpandedKeys={new Set(['permissions', 'users', 'roles'])}\n                        onCheck={(keys) => setCheckedKeys(keys)}\n                    />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default CheckboxMode;\n"
        },
        {
          "title": "DragDrop",
          "code": "import React, { useState } from 'react';\nimport type { DragDropInfo, TreeNode } from '../../../components';\nimport { TreeView } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst initialNodes: TreeNode[] = [\n    {\n        id: 'src',\n        label: 'src',\n        children: [\n            {\n                id: 'components',\n                label: 'components',\n                children: [\n                    { id: 'button', label: 'Button.tsx', isLeaf: true },\n                    { id: 'modal', label: 'Modal.tsx', isLeaf: true },\n                    { id: 'input', label: 'Input.tsx', isLeaf: true },\n                ],\n            },\n            {\n                id: 'hooks',\n                label: 'hooks',\n                children: [\n                    { id: 'use-state', label: 'useState.ts', isLeaf: true },\n                    { id: 'use-effect', label: 'useEffect.ts', isLeaf: true },\n                ],\n            },\n            { id: 'app', label: 'App.tsx', isLeaf: true },\n            { id: 'main', label: 'main.tsx', isLeaf: true },\n        ],\n    },\n    {\n        id: 'public',\n        label: 'public',\n        children: [\n            { id: 'index-html', label: 'index.html', isLeaf: true },\n            { id: 'favicon', label: 'favicon.ico', isLeaf: true },\n        ],\n    },\n];\n\nconst code = `import { TreeView } from 'fluxo-ui';\nimport type { TreeNode, DragDropInfo } from 'fluxo-ui';\n\n<TreeView\n  nodes={nodes}\n  draggable\n  defaultExpandedKeys={new Set(['src', 'components'])}\n  onDragDrop={(info: DragDropInfo) => {\n    console.log('Dragged:', info.dragNode.label);\n    console.log('Dropped on:', info.dropNode.label);\n    console.log('Position:', info.dropPosition);\n  }}\n/>`;\n\nconst DragDrop: React.FC = () => {\n    const [nodes, setNodes] = useState(initialNodes);\n\n    const handleDragDrop = (info: DragDropInfo) => {\n        console.log(`Dragged \"${info.dragNode.label}\" ${info.dropPosition} \"${info.dropNode.label}\"`);\n        setNodes((prev) => structuredClone(prev));\n    };\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Drag and Drop\"\n                description=\"Drag nodes to reorder or move them into other folders. Drop positions: before, inside, or after.\"\n            >\n                <div className=\"w-full max-w-sm\">\n                    <TreeView\n                        nodes={nodes}\n                        draggable\n                        defaultExpandedKeys={new Set(['src', 'components', 'hooks'])}\n                        onDragDrop={handleDragDrop}\n                    />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default DragDrop;\n"
        }
      ],
      "props": {
        "treeViewProps": {
          "nodes": {
            "type": "TreeNode[]",
            "required": true,
            "description": "Array of tree node data."
          },
          "expandedKeys": {
            "type": "Set<string>",
            "description": "Controlled set of expanded node IDs."
          },
          "selectedKeys": {
            "type": "Set<string>",
            "description": "Controlled set of selected node IDs."
          },
          "checkedKeys": {
            "type": "Set<string>",
            "description": "Controlled set of checked node IDs."
          },
          "defaultExpandedKeys": {
            "type": "Set<string>",
            "description": "Initially expanded node IDs (uncontrolled)."
          },
          "selectionMode": {
            "type": "'single' | 'multiple' | 'none'",
            "default": "'single'",
            "description": "Node selection behavior."
          },
          "checkboxes": {
            "type": "boolean",
            "default": "false",
            "description": "Show tri-state checkboxes on each node."
          },
          "draggable": {
            "type": "boolean",
            "default": "false",
            "description": "Enable drag-and-drop reordering."
          },
          "loadChildren": {
            "type": "(node: TreeNode) => Promise<TreeNode[]>",
            "description": "Async function to load children on expand."
          },
          "onExpand": {
            "type": "(keys: Set<string>, node: TreeNode) => void",
            "description": "Called when a node is expanded or collapsed."
          },
          "onSelect": {
            "type": "(keys: Set<string>, node: TreeNode) => void",
            "description": "Called when a node is selected."
          },
          "onCheck": {
            "type": "(keys: Set<string>, node: TreeNode) => void",
            "description": "Called when a node checkbox is toggled."
          },
          "onDragDrop": {
            "type": "(info: DragDropInfo) => void",
            "description": "Called when a node is dropped after dragging."
          },
          "className": {
            "type": "string",
            "description": "Additional CSS class for the tree container."
          },
          "nodeTemplate": {
            "type": "(node: TreeNode) => ReactNode",
            "description": "Custom render function for node content."
          },
          "filterText": {
            "type": "string",
            "description": "Filter string to show only matching nodes."
          },
          "ariaLabel": {
            "type": "string",
            "default": "'Tree'",
            "description": "Accessible name for the tree announced to screen readers."
          }
        },
        "nodeProps": {
          "id": {
            "type": "string",
            "required": true,
            "description": "Unique identifier for the node."
          },
          "label": {
            "type": "string",
            "required": true,
            "description": "Display text for the node."
          },
          "icon": {
            "type": "ReactNode",
            "description": "Icon displayed next to the label."
          },
          "children": {
            "type": "TreeNode[]",
            "description": "Child nodes (makes this a branch node)."
          },
          "isLeaf": {
            "type": "boolean",
            "description": "Mark as leaf to prevent expand toggle when no children."
          },
          "disabled": {
            "type": "boolean",
            "description": "Disable selection and checkbox for this node."
          },
          "data": {
            "type": "Record<string, unknown>",
            "description": "Custom data attached to the node."
          }
        }
      },
      "storyDir": "tree-view"
    },
    "VirtualList": {
      "name": "VirtualList",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React, { useMemo } from 'react';\nimport { VirtualList } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { VirtualList } from 'fluxo-ui';\n\n<VirtualList\n    items={items}\n    itemHeight={48}\n    height={400}\n    renderItem={(item) => <div>{item.name}</div>}\n    keyExtractor={(item) => item.id}\n/>`;\n\ninterface Row { id: number; name: string; email: string; }\n\nconst BasicUsage: React.FC = () => {\n    const items = useMemo<Row[]>(\n        () => Array.from({ length: 10_000 }, (_, i) => ({\n            id: i,\n            name: `Customer ${i + 1}`,\n            email: `customer${i + 1}@example.com`,\n        })),\n        [],\n    );\n\n    return (\n        <>\n            <ComponentDemo title=\"10,000-row virtual list\" description=\"Only the rows in the visible window are rendered, so scrolling stays smooth even with very long lists.\">\n                <div style={{ width: '100%', maxWidth: 480 }}>\n                    <div style={{ border: '1px solid var(--eui-border-subtle)', borderRadius: 8, overflow: 'hidden' }}>\n                        <VirtualList\n                            items={items}\n                            itemHeight={56}\n                            height={360}\n                            keyExtractor={(item) => item.id}\n                            renderItem={(item) => (\n                                <div style={{ padding: '8px 14px', borderBottom: '1px solid var(--eui-border-subtle)' }}>\n                                    <div style={{ fontWeight: 600, color: 'var(--eui-text)' }}>{item.name}</div>\n                                    <div style={{ fontSize: 12, color: 'var(--eui-text-muted)' }}>{item.email}</div>\n                                </div>\n                            )}\n                        />\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\"><CodeBlock code={code} language=\"tsx\" /></div>\n        </>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "InfiniteLoading",
          "code": "import React, { useCallback, useEffect, useState } from 'react';\nimport { VirtualList } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<VirtualList\n    items={items}\n    itemHeight={48}\n    height={360}\n    endReachedThreshold={150}\n    onEndReached={() => loadMore()}\n    renderItem={(item) => <Row item={item} />}\n/>`;\n\ninterface Row { id: number; label: string; }\n\nconst InfiniteLoading: React.FC = () => {\n    const [items, setItems] = useState<Row[]>(() =>\n        Array.from({ length: 30 }, (_, i) => ({ id: i, label: `Notification ${i + 1}` })),\n    );\n    const [loading, setLoading] = useState(false);\n\n    const loadMore = useCallback(() => {\n        if (loading) return;\n        setLoading(true);\n        window.setTimeout(() => {\n            setItems((prev) => {\n                const start = prev.length;\n                const next: Row[] = Array.from({ length: 30 }, (_, i) => ({ id: start + i, label: `Notification ${start + i + 1}` }));\n                return [...prev, ...next];\n            });\n            setLoading(false);\n        }, 600);\n    }, [loading]);\n\n    useEffect(() => {\n        // ensure cleanup on unmount\n        return () => undefined;\n    }, []);\n\n    return (\n        <>\n            <ComponentDemo title=\"Infinite scroll via onEndReached\" description=\"Fires when scrolled within endReachedThreshold of the bottom. Pair with VirtualList for unbounded feeds.\">\n                <div style={{ width: '100%', maxWidth: 480 }}>\n                    <div style={{ border: '1px solid var(--eui-border-subtle)', borderRadius: 8, overflow: 'hidden' }}>\n                        <VirtualList\n                            items={items}\n                            itemHeight={52}\n                            height={320}\n                            endReachedThreshold={120}\n                            onEndReached={loadMore}\n                            keyExtractor={(item) => item.id}\n                            renderItem={(item) => (\n                                <div style={{ padding: '12px 14px', borderBottom: '1px solid var(--eui-border-subtle)', color: 'var(--eui-text)' }}>{item.label}</div>\n                            )}\n                        />\n                    </div>\n                    <div style={{\n                        marginTop: 12,\n                        padding: '10px 14px',\n                        background: 'var(--eui-bg-subtle)',\n                        border: '1px solid var(--eui-border-subtle)',\n                        borderRadius: 6,\n                        fontSize: 12,\n                        color: 'var(--eui-text-muted)',\n                    }}>\n                        Loaded <strong style={{ color: 'var(--eui-text)' }}>{items.length}</strong> items{loading ? ' · loading more…' : ''}\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\"><CodeBlock code={code} language=\"tsx\" /></div>\n        </>\n    );\n};\n\nexport default InfiniteLoading;\n"
        },
        {
          "title": "Variants",
          "code": "import React, { useMemo } from 'react';\nimport { VirtualList } from '../../../components';\nimport type { VirtualListVariant } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<VirtualList variant=\"divided\" ... />\n<VirtualList variant=\"card\" ... />`;\n\ninterface Row { id: number; title: string; subtitle: string; }\n\nconst useRows = (count: number) =>\n    useMemo<Row[]>(\n        () => Array.from({ length: count }, (_, i) => ({\n            id: i,\n            title: `Row ${i + 1}`,\n            subtitle: 'Lorem ipsum dolor sit amet',\n        })),\n        [count],\n    );\n\nconst Preview: React.FC<{ variant: VirtualListVariant; description: string }> = ({ variant, description }) => {\n    const rows = useRows(500);\n    return (\n        <ComponentDemo title={`variant=\"${variant}\"`} description={description}>\n            <div style={{ width: '100%', maxWidth: 480, border: '1px solid var(--eui-border-subtle)', borderRadius: 8, overflow: 'hidden' }}>\n                <VirtualList\n                    items={rows}\n                    itemHeight={variant === 'card' ? 96 : 56}\n                    height={280}\n                    variant={variant}\n                    keyExtractor={(r) => r.id}\n                    renderItem={(r) => (\n                        <div style={{ padding: '10px 14px' }}>\n                            <div style={{ color: 'var(--eui-text)', fontWeight: 600 }}>{r.title}</div>\n                            <div style={{ fontSize: 12, color: 'var(--eui-text-muted)', marginTop: 2 }}>{r.subtitle}</div>\n                        </div>\n                    )}\n                />\n            </div>\n        </ComponentDemo>\n    );\n};\n\nconst Variants: React.FC = () => (\n    <>\n        <Preview variant=\"plain\" description=\"No separators — pair with custom border styling on each row.\" />\n        <div className=\"mt-4\"><Preview variant=\"divided\" description=\"A subtle hairline between rows.\" /></div>\n        <div className=\"mt-4\"><Preview variant=\"card\" description=\"Each row rendered as a rounded card with breathing room.\" /></div>\n        <div className=\"mt-4\"><CodeBlock code={code} language=\"tsx\" /></div>\n    </>\n);\n\nexport default Variants;\n"
        }
      ],
      "props": {
        "virtualListProps": {
          "items": {
            "type": "T[]",
            "required": true,
            "description": "Source array. Only the rows in the visible window are rendered."
          },
          "itemHeight": {
            "type": "number | (index: number, item: T) => number",
            "description": "Row height. Pass a number for uniform rows or a function for per-row heights. When omitted, estimatedItemHeight is used."
          },
          "renderItem": {
            "type": "(item: T, index: number) => ReactNode",
            "required": true,
            "description": "Renderer for each row."
          },
          "keyExtractor": {
            "type": "(item: T, index: number) => Key",
            "description": "Optional key extractor for stable row identity."
          },
          "overscan": {
            "type": "number",
            "default": "4",
            "description": "Number of rows to render before/after the visible window."
          },
          "height": {
            "type": "string | number",
            "default": "'100%'",
            "description": "CSS height of the scrollable container."
          },
          "estimatedItemHeight": {
            "type": "number",
            "default": "56",
            "description": "Fallback row height when itemHeight is not provided."
          },
          "variant": {
            "type": "'plain' | 'divided' | 'card'",
            "default": "'plain'",
            "description": "Visual style. 'divided' draws a separator between rows; 'card' renders each row in a card with margin."
          },
          "emptyState": {
            "type": "ReactNode",
            "description": "Optional content rendered when items is empty."
          },
          "onEndReached": {
            "type": "() => void",
            "description": "Fired when the scroll position is within endReachedThreshold of the bottom. Pairs with infinite loading."
          },
          "endReachedThreshold": {
            "type": "number",
            "default": "200",
            "description": "Pixels from the bottom at which onEndReached should fire."
          },
          "className": {
            "type": "string",
            "description": "Additional CSS class for the scroller."
          },
          "ariaLabel": {
            "type": "string",
            "description": "Accessible name for the list landmark."
          }
        }
      },
      "storyDir": "virtual-list"
    },
    "WeekDaySelector": {
      "name": "WeekDaySelector",
      "importFrom": "fluxo-ui",
      "examples": [
        {
          "title": "BasicUsage",
          "code": "import React, { useState } from 'react';\nimport { WeekDaySelector } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `import { WeekDaySelector } from 'fluxo-ui';\n\nconst [day, setDay] = useState<number | null>(1);\n<WeekDaySelector value={day} onChange={setDay} />\n\nconst [days, setDays] = useState<number[]>([1, 3, 5]);\n<WeekDaySelector multiple value={days} onChange={setDays} />`;\n\nconst BasicUsage: React.FC = () => {\n    const [day, setDay] = useState<number | null>(1);\n    const [days, setDays] = useState<number[]>([1, 3, 5]);\n\n    return (\n        <>\n            <ComponentDemo title=\"Single & Multiple Selection\" description=\"Single returns a day number, multiple returns an array.\">\n                <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 20 }}>\n                    <div>\n                        <div style={{ fontSize: 12, marginBottom: 8, color: 'var(--eui-text-muted)' }}>Single (selected: {day ?? 'none'})</div>\n                        <WeekDaySelector value={day} onChange={setDay} />\n                    </div>\n                    <div>\n                        <div style={{ fontSize: 12, marginBottom: 8, color: 'var(--eui-text-muted)' }}>Multiple (selected: [{days.join(', ')}])</div>\n                        <WeekDaySelector multiple value={days} onChange={setDays} />\n                    </div>\n                    <div style={{ padding: '10px 14px', background: 'var(--eui-bg-subtle)', border: '1px solid var(--eui-border-subtle)', borderRadius: 6, fontSize: 13, color: 'var(--eui-text)' }}>\n                        Days are 0-indexed: 0 = Sunday, 6 = Saturday.\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "Fills",
          "code": "import React from 'react';\nimport { WeekDaySelector } from '../../../components';\nimport type { WeekDayFill, WeekDayVariant } from '../../../components/week-day-selector';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<WeekDaySelector fill=\"solid\"    variant=\"primary\" multiple defaultValue={[1, 3, 5]} />\n<WeekDaySelector fill=\"outlined\" variant=\"primary\" multiple defaultValue={[1, 3, 5]} />\n<WeekDaySelector fill=\"subtle\"   variant=\"primary\" multiple defaultValue={[1, 3, 5]} />`;\n\nconst fills: WeekDayFill[] = ['solid', 'outlined', 'subtle'];\nconst variants: WeekDayVariant[] = ['default', 'primary', 'success', 'danger'];\n\nconst Fills: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Fill Styles\" description=\"Solid (filled background), outlined (border-only), or subtle (tinted background).\">\n            <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 22 }}>\n                {fills.map((fill) => (\n                    <div key={fill}>\n                        <div style={{ fontSize: 12, marginBottom: 8, color: 'var(--eui-text-muted)', textTransform: 'capitalize' }}>{fill}</div>\n                        <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>\n                            {variants.map((v) => (\n                                <div key={v} style={{ display: 'flex', alignItems: 'center', gap: 12 }}>\n                                    <div style={{ width: 60, fontSize: 12, color: 'var(--eui-text-muted)', textTransform: 'capitalize' }}>{v}</div>\n                                    <WeekDaySelector fill={fill} variant={v} multiple defaultValue={[1, 3, 5]} />\n                                </div>\n                            ))}\n                        </div>\n                    </div>\n                ))}\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default Fills;\n"
        },
        {
          "title": "Shapes",
          "code": "import React from 'react';\nimport { WeekDaySelector } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<WeekDaySelector shape=\"rounded\" defaultValue={2} />\n<WeekDaySelector shape=\"squared\" defaultValue={2} />\n<WeekDaySelector shape=\"circle\" defaultValue={2} />`;\n\nconst Shapes: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Shapes\" description=\"Rounded pill, squared, or circle.\">\n            <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 18 }}>\n                <div>\n                    <div style={{ fontSize: 12, marginBottom: 6, color: 'var(--eui-text-muted)' }}>Rounded</div>\n                    <WeekDaySelector shape=\"rounded\" defaultValue={2} />\n                </div>\n                <div>\n                    <div style={{ fontSize: 12, marginBottom: 6, color: 'var(--eui-text-muted)' }}>Squared</div>\n                    <WeekDaySelector shape=\"squared\" defaultValue={2} />\n                </div>\n                <div>\n                    <div style={{ fontSize: 12, marginBottom: 6, color: 'var(--eui-text-muted)' }}>Circle</div>\n                    <WeekDaySelector shape=\"circle\" defaultValue={2} />\n                </div>\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default Shapes;\n"
        },
        {
          "title": "SizesVariants",
          "code": "import React from 'react';\nimport { WeekDaySelector } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<WeekDaySelector size=\"sm\" variant=\"primary\" defaultValue={3} />\n<WeekDaySelector size=\"md\" variant=\"success\" defaultValue={3} />\n<WeekDaySelector size=\"lg\" variant=\"danger\" defaultValue={3} />`;\n\nconst SizesVariants: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Sizes & Color Variants\" description=\"Three sizes and four color variants.\">\n            <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 18 }}>\n                <div>\n                    <div style={{ fontSize: 12, marginBottom: 6, color: 'var(--eui-text-muted)' }}>sm / primary</div>\n                    <WeekDaySelector size=\"sm\" variant=\"primary\" defaultValue={3} />\n                </div>\n                <div>\n                    <div style={{ fontSize: 12, marginBottom: 6, color: 'var(--eui-text-muted)' }}>md / success</div>\n                    <WeekDaySelector size=\"md\" variant=\"success\" defaultValue={3} />\n                </div>\n                <div>\n                    <div style={{ fontSize: 12, marginBottom: 6, color: 'var(--eui-text-muted)' }}>lg / danger</div>\n                    <WeekDaySelector size=\"lg\" variant=\"danger\" defaultValue={3} />\n                </div>\n                <div>\n                    <div style={{ fontSize: 12, marginBottom: 6, color: 'var(--eui-text-muted)' }}>default (neutral)</div>\n                    <WeekDaySelector variant=\"default\" defaultValue={3} />\n                </div>\n                <div>\n                    <div style={{ fontSize: 12, marginBottom: 6, color: 'var(--eui-text-muted)' }}>firstDayOfWeek = 1 (Monday start), disabled weekend</div>\n                    <WeekDaySelector firstDayOfWeek={1} disabledDays={[0, 6]} multiple defaultValue={[1, 2, 3, 4, 5]} />\n                </div>\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default SizesVariants;\n"
        },
        {
          "title": "Spacing",
          "code": "import React from 'react';\nimport { WeekDaySelector } from '../../../components';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\nconst code = `<WeekDaySelector spacing=\"spaced\" multiple defaultValue={[1, 3]} />\n<WeekDaySelector spacing=\"joined\" multiple defaultValue={[1, 3]} />`;\n\nconst Spacing: React.FC = () => (\n    <>\n        <ComponentDemo title=\"Spacing\" description=\"Spaced or joined (segmented) layouts.\">\n            <div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 20 }}>\n                <div>\n                    <div style={{ fontSize: 12, marginBottom: 6, color: 'var(--eui-text-muted)' }}>Spaced</div>\n                    <WeekDaySelector spacing=\"spaced\" multiple defaultValue={[1, 3]} />\n                </div>\n                <div>\n                    <div style={{ fontSize: 12, marginBottom: 6, color: 'var(--eui-text-muted)' }}>Joined (no gap, shared borders)</div>\n                    <WeekDaySelector spacing=\"joined\" multiple defaultValue={[1, 3]} />\n                </div>\n                <div>\n                    <div style={{ fontSize: 12, marginBottom: 6, color: 'var(--eui-text-muted)' }}>Joined + squared</div>\n                    <WeekDaySelector spacing=\"joined\" shape=\"squared\" multiple defaultValue={[2, 4, 6]} />\n                </div>\n            </div>\n        </ComponentDemo>\n        <div className=\"mt-4\">\n            <CodeBlock code={code} language=\"tsx\" />\n        </div>\n    </>\n);\n\nexport default Spacing;\n"
        }
      ],
      "props": {
        "weekDayProps": {
          "value": {
            "type": "number | number[] | null",
            "description": "Controlled value. Single returns number, multiple returns number[]."
          },
          "defaultValue": {
            "type": "number | number[] | null",
            "description": "Uncontrolled default value."
          },
          "multiple": {
            "type": "boolean",
            "default": "false",
            "description": "Enable multi-day selection."
          },
          "shape": {
            "type": "'rounded' | 'squared' | 'circle'",
            "default": "'rounded'",
            "description": "Button shape."
          },
          "spacing": {
            "type": "'spaced' | 'joined'",
            "default": "'spaced'",
            "description": "Gap between items (joined shares borders)."
          },
          "size": {
            "type": "'sm' | 'md' | 'lg'",
            "default": "'md'",
            "description": "Button size."
          },
          "variant": {
            "type": "'default' | 'primary' | 'success' | 'danger'",
            "default": "'primary'",
            "description": "Selected color variant."
          },
          "fill": {
            "type": "'solid' | 'outlined' | 'subtle'",
            "default": "'solid'",
            "description": "How selected items are styled — filled background, border-only, or tinted background."
          },
          "firstDayOfWeek": {
            "type": "number",
            "default": "0",
            "description": "First day of week (0=Sun, 1=Mon)."
          },
          "labels": {
            "type": "string[]",
            "description": "Custom day labels. Defaults to [Su, Mo, Tu, We, Th, Fr, Sa]."
          },
          "disabledDays": {
            "type": "number[]",
            "description": "Array of disabled day indexes (0–6)."
          },
          "disabled": {
            "type": "boolean",
            "default": "false",
            "description": "Disable the entire control."
          },
          "onChange": {
            "type": "(value) => void",
            "description": "Called on selection change."
          }
        }
      },
      "storyDir": "week-day-selector"
    },
    "ComponentEvent": {
      "name": "ComponentEvent",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "ListItem": {
      "name": "ListItem",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "BreadcrumbItem": {
      "name": "BreadcrumbItem",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "BreadcrumbProps": {
      "name": "BreadcrumbProps",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "ContextMenuManager": {
      "name": "ContextMenuManager",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "ThemeProvider": {
      "name": "ThemeProvider",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "DeferredViewProps": {
      "name": "DeferredViewProps",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "DrawerProps": {
      "name": "DrawerProps",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "DrawerPosition": {
      "name": "DrawerPosition",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "CarouselProps": {
      "name": "CarouselProps",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "CarouselSlide": {
      "name": "CarouselSlide",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "CarouselThumbnailAction": {
      "name": "CarouselThumbnailAction",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "CarouselTrailingThumbnail": {
      "name": "CarouselTrailingThumbnail",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "InfiniteScrollProps": {
      "name": "InfiniteScrollProps",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "FileKindIcon": {
      "name": "FileKindIcon",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "FileBrowserProps": {
      "name": "FileBrowserProps",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "FileBrowserItem": {
      "name": "FileBrowserItem",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "FileBrowserItemContext": {
      "name": "FileBrowserItemContext",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "FileBrowserView": {
      "name": "FileBrowserView",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "FileBrowserColumn": {
      "name": "FileBrowserColumn",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "FileBrowserThumbnailFit": {
      "name": "FileBrowserThumbnailFit",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "FileKind": {
      "name": "FileKind",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "RejectedFile": {
      "name": "RejectedFile",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "DateRangeValue": {
      "name": "DateRangeValue",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "DateSelectedCallbackArg": {
      "name": "DateSelectedCallbackArg",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "RangeOption": {
      "name": "RangeOption",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "SelectionMode": {
      "name": "SelectionMode",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "DragDropProvider": {
      "name": "DragDropProvider",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "Draggable": {
      "name": "Draggable",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "Droppable": {
      "name": "Droppable",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "DragDropProviderProps": {
      "name": "DragDropProviderProps",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "DraggableProps": {
      "name": "DraggableProps",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "DraggableRenderProps": {
      "name": "DraggableRenderProps",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "DragItem": {
      "name": "DragItem",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "DropResult": {
      "name": "DropResult",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "DragPreviewProp": {
      "name": "DragPreviewProp",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "DropIndicator": {
      "name": "DropIndicator",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "DropOrientation": {
      "name": "DropOrientation",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "DroppableProps": {
      "name": "DroppableProps",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "DroppableRenderProps": {
      "name": "DroppableRenderProps",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "SortableChangeEvent": {
      "name": "SortableChangeEvent",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "SortableProps": {
      "name": "SortableProps",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "DropPosition": {
      "name": "DropPosition",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "UseDragReturn": {
      "name": "UseDragReturn",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "UseDropReturn": {
      "name": "UseDropReturn",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "UseDropSpec": {
      "name": "UseDropSpec",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "DragLayerState": {
      "name": "DragLayerState",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "FabPosition": {
      "name": "FabPosition",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "FabProps": {
      "name": "FabProps",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "FabSize": {
      "name": "FabSize",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "FabVariant": {
      "name": "FabVariant",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "JsonEditorProps": {
      "name": "JsonEditorProps",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "JsonEditorSize": {
      "name": "JsonEditorSize",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "JsonValue": {
      "name": "JsonValue",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "JsonObject": {
      "name": "JsonObject",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "JsonArray": {
      "name": "JsonArray",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "MaskedInputProps": {
      "name": "MaskedInputProps",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "NotificationCenterProps": {
      "name": "NotificationCenterProps",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "NotificationItem": {
      "name": "NotificationItem",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "ProgressBarLayout": {
      "name": "ProgressBarLayout",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "ProgressBarProps": {
      "name": "ProgressBarProps",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "ProgressBarSegment": {
      "name": "ProgressBarSegment",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "ProgressBarSize": {
      "name": "ProgressBarSize",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "ProgressBarVariant": {
      "name": "ProgressBarVariant",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "RadioButtonGroup": {
      "name": "RadioButtonGroup",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "SelectButtonVariant": {
      "name": "SelectButtonVariant",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "SpeedDial": {
      "name": "SpeedDial",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "SpeedDialDirection": {
      "name": "SpeedDialDirection",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "SpeedDialItem": {
      "name": "SpeedDialItem",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "SpeedDialLayout": {
      "name": "SpeedDialLayout",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "SpeedDialProps": {
      "name": "SpeedDialProps",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "SpeedDialSize": {
      "name": "SpeedDialSize",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "SpeedDialVariant": {
      "name": "SpeedDialVariant",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "StepItem": {
      "name": "StepItem",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "StepperLabelPlacement": {
      "name": "StepperLabelPlacement",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "StepperLayout": {
      "name": "StepperLayout",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "StepperOrientation": {
      "name": "StepperOrientation",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "StepperProps": {
      "name": "StepperProps",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "StepperSize": {
      "name": "StepperSize",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "StepperVariant": {
      "name": "StepperVariant",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "StepStatus": {
      "name": "StepStatus",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "Column": {
      "name": "Column",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "TextArea": {
      "name": "TextArea",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "TooltipManager": {
      "name": "TooltipManager",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "StepTour": {
      "name": "StepTour",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "DragDropInfo": {
      "name": "DragDropInfo",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "TreeNode": {
      "name": "TreeNode",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    },
    "TreeViewProps": {
      "name": "TreeViewProps",
      "importFrom": "fluxo-ui",
      "examples": [],
      "props": {}
    }
  },
  "storeApi": {
    "groups": {
      "storeApiProps": {
        "create(initializer, middlewares?)": {
          "type": "(initializer: () => T, middlewares?: Middleware<T>[]) => Store<T>",
          "description": "Create a new store with initial state and optional middleware",
          "default": "-"
        },
        "store.getState()": {
          "type": "() => T",
          "description": "Get the current state snapshot (includes computed properties)",
          "default": "-"
        },
        "store.setState(update)": {
          "type": "(partial: Partial<T>) => void",
          "description": "Merge partial state into current state (batched via microtask)",
          "default": "-"
        },
        "store.setState(updater)": {
          "type": "(fn: (state: T) => Partial<T>) => void",
          "description": "Update state using an updater function for safe reads",
          "default": "-"
        },
        "store.on(event, listener)": {
          "type": "(event: 'init' | 'change', listener) => unsubscribe",
          "description": "Subscribe to all state changes or initialization",
          "default": "-"
        },
        "store.on(event, path, listener)": {
          "type": "(event: 'change', path: string, listener) => unsubscribe",
          "description": "Subscribe to changes on a specific state path",
          "default": "-"
        },
        "store.reset()": {
          "type": "() => void",
          "description": "Reset state to the initial value from the initializer function",
          "default": "-"
        },
        "store.compute(name, fn, deps)": {
          "type": "(name: string, fn: (state: T) => R, deps: string[]) => void",
          "description": "Register a computed property with dependency tracking",
          "default": "-"
        },
        "createHook(store)": {
          "type": "(store: Store<T>) => useStore",
          "description": "Create a React hook bound to a store for reactive component integration",
          "default": "-"
        },
        "useStore(selector?, equalityFn?)": {
          "type": "(selector?, equalityFn?) => T | R",
          "description": "React hook returned by createHook. Optional selector for derived slices",
          "default": "-"
        }
      },
      "sliceApiProps": {
        "createSlice(name, initializer, middlewares?)": {
          "type": "(name: string, initializer: () => T, middlewares?: Middleware<T>[]) => Slice<T>",
          "description": "Create a named slice. Usable directly as a Store<T> in standalone mode, or adopted by combineSlices() for composition",
          "default": "-"
        },
        "combineSlices(slices, middlewares?)": {
          "type": "(slices: Record<string, Slice>, middlewares?) => CombinedStore",
          "description": "Compose multiple slices into a single store. Bidirectional sync: slice writes notify the combined store, combined writes notify the relevant slice's subscribers",
          "default": "-"
        },
        "slice.sliceName": {
          "type": "string",
          "description": "The name passed to createSlice. Used as the key in combined state",
          "default": "-"
        },
        "slice.getState() / setState() / on() / reset()": {
          "type": "Same as Store<T>",
          "description": "Slices implement the full Store<T> interface — works identically standalone or after being combined",
          "default": "-"
        },
        "combinedStore.slices": {
          "type": "Record<string, Slice>",
          "description": "The slices passed to combineSlices, exposed for direct slice access",
          "default": "-"
        },
        "isSlice(value) / isCombinedStore(value)": {
          "type": "(value: unknown) => boolean",
          "description": "Type guards for runtime checks",
          "default": "-"
        }
      },
      "middlewareApiProps": {
        "persistMiddleware(options)": {
          "type": "(options: PersistOptions<T>) => Middleware<T>",
          "description": "Persist state. Options: storage ('local' | 'session' | Storage | AsyncStorageAdapter), key, include/exclude paths, version + migrate, debounceMs, custom serialize/deserialize, onError",
          "default": "-"
        },
        "undoRedoMiddleware(options)": {
          "type": "(options: UndoRedoOptions) => Middleware<T>",
          "description": "Undo/redo history. Options: maxHistorySize, paths (scoped undo), coalesceMs (group rapid edits), maxBytes (memory cap). Returned store gets undo, redo, beginGroup, endGroup, clearHistory, canUndo, canRedo",
          "default": "-"
        },
        "optimisticMiddleware(options)": {
          "type": "(options: OptimisticOptions<T>) => Middleware<T>",
          "description": "Apply state changes locally, run an async commit, and roll back automatically on rejection. Returned store gets optimistic(setStateLike), isPending(), pendingCount()",
          "default": "-"
        },
        "syncMiddleware(options)": {
          "type": "(options: SyncOptions<T>) => Middleware<T>",
          "description": "Sync state across instances via a pluggable transport (BroadcastChannel, storage event, WebSocket, custom). Conflict resolve modes: 'remote-wins' | 'local-wins' | 'merge' | custom resolver",
          "default": "-"
        },
        "broadcastChannelTransport / storageEventTransport / webSocketTransport": {
          "type": "(...) => SyncTransport",
          "description": "Built-in transports for syncMiddleware. Implement SyncTransport ({ send, onReceive, close? }) to add your own",
          "default": "-"
        },
        "validationMiddleware(options)": {
          "type": "(options: ValidationOptions<T>) => Middleware<T>",
          "description": "Reject or warn on invalid state. Options accept either a function validator, a Zod/Valibot-style schema (parse / safeParse), and/or an asyncValidator for server-side checks. behavior: 'reject' | 'warn'",
          "default": "-"
        },
        "throttleMiddleware / debounceMiddleware": {
          "type": "(delay: number) => Middleware<T>",
          "description": "Rate-limit setState calls. Throttle fires on leading + trailing edges; debounce only after activity stops",
          "default": "-"
        },
        "loggerMiddleware(predicate?)": {
          "type": "(predicate?: (state, prev?) => boolean) => Middleware<T>",
          "description": "Console-log init and change events. Optional predicate filters which changes are logged",
          "default": "-"
        },
        "devToolsMiddleware": {
          "type": "Middleware<T>",
          "description": "Send state changes to window.__FLUXO_DEVTOOLS__ if present",
          "default": "-"
        },
        "Authoring middleware": {
          "type": "(store: Store<T>) => Store<T>",
          "description": "A middleware is just a function. Common patterns: wrap setState (throttle, debounce), subscribe via store.on() (logger, persist), augment the returned store with new methods (undoRedo). Order in create(init, [a, b, c]) is left-to-right wrapping",
          "default": "-"
        }
      },
      "modelApiProps": {
        "modelConfigProps": {
          "createWithDefaults": {
            "type": "(id: any) => T",
            "description": "Factory function returning default state for new model instances",
            "default": "-"
          },
          "selectId": {
            "type": "(state: T) => any",
            "description": "Extract the unique identifier from the model state",
            "default": "-"
          },
          "nextId": {
            "type": "() => any",
            "description": "Generate a new unique ID when creating models",
            "default": "-"
          },
          "loadItem": {
            "type": "(id: any) => Promise<T>",
            "description": "Async function to load a single item by ID from a remote source",
            "default": "-"
          },
          "loadItems": {
            "type": "(options: PageOptions) => Promise<T[]>",
            "description": "Async function to load a paginated list of items",
            "default": "-"
          },
          "onCreate": {
            "type": "(data: T, options: ChangeOptions<T>) => Promise<void>",
            "description": "Handler called when saving a new model (no existing ID)",
            "default": "-"
          },
          "onUpdate": {
            "type": "(data: T, options: ChangeOptions<T>) => Promise<void>",
            "description": "Handler called when saving an existing model",
            "default": "-"
          },
          "onDelete": {
            "type": "(data: T) => Promise<void>",
            "description": "Handler called when deleting a model",
            "default": "-"
          },
          "validate": {
            "type": "(state: T) => errors | undefined",
            "description": "Validation function returning field-level errors or undefined if valid",
            "default": "-"
          },
          "validateBehavior": {
            "type": "'change' | 'save'",
            "description": "When to run validation: on every state change or only on save",
            "default": "-"
          },
          "persist": {
            "type": "boolean | 'local' | 'session' | ((store: T) => void)",
            "description": "Enable state persistence to localStorage, sessionStorage, or a custom function",
            "default": "false"
          },
          "loadFromPersist": {
            "type": "() => T | undefined",
            "description": "Custom function to load persisted state on initialization",
            "default": "-"
          },
          "saveOnChange": {
            "type": "boolean",
            "description": "Automatically save (debounced 500ms) whenever state changes",
            "default": "false"
          }
        }
      }
    },
    "examples": {
      "basic": [
        {
          "title": "BasicUsage",
          "code": "import React from 'react';\nimport { Button } from '../../../components';\nimport { create, createHook } from '../../../store';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\ninterface CounterState {\n    count: number;\n}\n\nconst counterStore = create<CounterState>(() => ({ count: 0 }));\nconst useCounter = createHook(counterStore);\n\nconst code = `import { create, createHook } from 'fluxo-ui/store';\n\ninterface CounterState {\n  count: number;\n}\n\nconst counterStore = create<CounterState>(() => ({ count: 0 }));\nconst useCounter = createHook(counterStore);\n\nfunction Counter() {\n  const { count } = useCounter();\n\n  return (\n    <div>\n      <span>Count: {count}</span>\n      <Button label=\"Increment\"\n        onClick={() => counterStore.setState(s => ({ count: s.count + 1 }))} />\n      <Button label=\"Decrement\"\n        onClick={() => counterStore.setState(s => ({ count: s.count - 1 }))} />\n      <Button label=\"Reset\" variant=\"secondary\"\n        onClick={() => counterStore.reset()} />\n    </div>\n  );\n}`;\n\nconst CounterDisplay: React.FC = () => {\n    const { count } = useCounter();\n\n    return (\n        <div className=\"flex flex-col items-center gap-4\">\n            <div className=\"text-5xl font-bold tabular-nums text-[var(--eui-primary)]\">{count}</div>\n            <div className=\"flex gap-3\">\n                <Button label=\"Decrement\" size=\"sm\" onClick={() => counterStore.setState((s) => ({ count: s.count - 1 }))} />\n                <Button label=\"Increment\" size=\"sm\" onClick={() => counterStore.setState((s) => ({ count: s.count + 1 }))} />\n                <Button label=\"Reset\" size=\"sm\" variant=\"secondary\" onClick={() => counterStore.reset()} />\n            </div>\n        </div>\n    );\n};\n\nconst BasicUsage: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo title=\"Counter Store\" description=\"A simple counter using create() and createHook() for React integration\">\n                <CounterDisplay />\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default BasicUsage;\n"
        },
        {
          "title": "BatchedUpdates",
          "code": "import cn from 'classnames';\nimport React, { useRef } from 'react';\nimport { Button } from '../../../components';\nimport { create, createHook } from '../../../store';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\n\ninterface BatchState {\n    count: number;\n}\n\nconst batchStore = create<BatchState>(() => ({ count: 0 }));\nconst useBatchStore = createHook(batchStore);\n\nconst code = `import { create, createHook } from 'fluxo-ui/store';\n\nconst store = create<{ count: number }>(() => ({ count: 0 }));\nconst useStore = createHook(store);\n\nfunction BatchDemo() {\n  const renderCount = useRef(0);\n  renderCount.current++;\n\n  const { count } = useStore();\n\n  const handleBatchIncrement = () => {\n    // All three calls are batched into a single re-render\n    store.setState((s) => ({ count: s.count + 1 }));\n    store.setState((s) => ({ count: s.count + 1 }));\n    store.setState((s) => ({ count: s.count + 1 }));\n  };\n\n  return (\n    <div>\n      <p>Count: {count}</p>\n      <p>Render count: {renderCount.current}</p>\n      <Button label=\"+3 (Batched)\" onClick={handleBatchIncrement} />\n    </div>\n  );\n}`;\n\nconst BatchDemo: React.FC = () => {\n    const { isDark } = useStoryTheme();\n    const renderCount = useRef(0);\n    renderCount.current++;\n\n    const { count } = useBatchStore();\n\n    const handleBatchIncrement = () => {\n        batchStore.setState((s) => ({ count: s.count + 1 }));\n        batchStore.setState((s) => ({ count: s.count + 1 }));\n        batchStore.setState((s) => ({ count: s.count + 1 }));\n    };\n\n    return (\n        <div className=\"flex flex-col items-center gap-5 w-full max-w-sm mx-auto\">\n            <div className=\"flex gap-8\">\n                <div className=\"text-center\">\n                    <div className={cn('text-xs uppercase tracking-wide mb-1', { 'text-gray-500': isDark, 'text-gray-400': !isDark })}>\n                        Count\n                    </div>\n                    <div className=\"text-4xl font-bold tabular-nums text-[var(--eui-primary)]\">{count}</div>\n                </div>\n                <div className=\"text-center\">\n                    <div className={cn('text-xs uppercase tracking-wide mb-1', { 'text-gray-500': isDark, 'text-gray-400': !isDark })}>\n                        Renders\n                    </div>\n                    <div className={cn('text-4xl font-bold tabular-nums', { 'text-amber-400': isDark, 'text-amber-600': !isDark })}>\n                        {renderCount.current}\n                    </div>\n                </div>\n            </div>\n            <div\n                className={cn('text-xs text-center px-4 py-2 rounded-lg', {\n                    'bg-white/5 text-gray-400': isDark,\n                    'bg-gray-100 text-gray-500': !isDark,\n                })}\n            >\n                Three setState calls in one handler produce only one re-render thanks to microtask batching. In React dev mode (StrictMode),\n                render count may increment by 2 — this is expected and does not occur in production builds.\n            </div>\n            <div className=\"flex gap-3\">\n                <Button label=\"+3 (Batched)\" size=\"sm\" onClick={handleBatchIncrement} />\n                <Button label=\"+1\" size=\"sm\" onClick={() => batchStore.setState((s) => ({ count: s.count + 1 }))} />\n                <Button label=\"Reset\" size=\"sm\" variant=\"secondary\" onClick={() => batchStore.reset()} />\n            </div>\n        </div>\n    );\n};\n\nconst BatchedUpdates: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo\n                title=\"Batched Updates\"\n                description=\"Multiple setState calls within one synchronous handler are batched into a single re-render\"\n            >\n                <BatchDemo />\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default BatchedUpdates;\n"
        },
        {
          "title": "ComputedProperties",
          "code": "import cn from 'classnames';\nimport React from 'react';\nimport { Button, TextInput } from '../../../components';\nimport { create, createHook } from '../../../store';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\n\ninterface UserState {\n    firstName: string;\n    lastName: string;\n}\n\nconst userStore = create<UserState>(() => ({\n    firstName: 'John',\n    lastName: 'Doe',\n}));\n\nuserStore.compute('fullName', (state) => `${state.firstName} ${state.lastName}`, ['firstName', 'lastName']);\nuserStore.compute('initials', (state) => `${state.firstName.charAt(0)}${state.lastName.charAt(0)}`.toUpperCase(), [\n    'firstName',\n    'lastName',\n]);\n\nconst useUser = createHook(userStore);\n\nconst syncCode = `import { create, createHook } from 'fluxo-ui/store';\n\nconst userStore = create<UserState>(() => ({\n  firstName: 'John',\n  lastName: 'Doe',\n}));\n\nuserStore.compute(\n  'fullName',\n  (state) => \\`\\${state.firstName} \\${state.lastName}\\`,\n  ['firstName', 'lastName']\n);\n\nuserStore.compute(\n  'initials',\n  (state) => \\`\\${state.firstName.charAt(0)}\\${state.lastName.charAt(0)}\\`.toUpperCase(),\n  ['firstName', 'lastName']\n);\n\nconst useUser = createHook(userStore);\n\nfunction UserCard() {\n  const state = useUser();\n  const { firstName, lastName, fullName, initials } = state as any;\n\n  return (\n    <div>\n      <div className=\"avatar\">{initials}</div>\n      <div>{fullName}</div>\n      <TextInput value={firstName}\n        onChange={(e) => userStore.setState({ firstName: e.value })} />\n      <TextInput value={lastName}\n        onChange={(e) => userStore.setState({ lastName: e.value })} />\n    </div>\n  );\n}`;\n\nconst SyncUserCard: React.FC = () => {\n    const { isDark } = useStoryTheme();\n    const state = useUser() as any;\n    const { firstName, lastName, fullName, initials } = state;\n\n    return (\n        <div className=\"flex flex-col items-center gap-5 w-full max-w-md mx-auto\">\n            <div className=\"flex items-center gap-4\">\n                <div className=\"w-14 h-14 rounded-full bg-[var(--eui-primary)] flex items-center justify-center text-white text-lg font-bold\">\n                    {initials}\n                </div>\n                <div>\n                    <div className={cn('text-lg font-semibold', { 'text-gray-100': isDark, 'text-gray-800': !isDark })}>{fullName}</div>\n                    <div className={cn('text-sm', { 'text-gray-400': isDark, 'text-gray-500': !isDark })}>\n                        Computed from firstName + lastName\n                    </div>\n                </div>\n            </div>\n            <div className=\"flex gap-3 w-full\">\n                <TextInput value={firstName} onChange={(e) => userStore.setState({ firstName: e.value })} placeholder=\"First Name\" />\n                <TextInput value={lastName} onChange={(e) => userStore.setState({ lastName: e.value })} placeholder=\"Last Name\" />\n            </div>\n        </div>\n    );\n};\n\ninterface AsyncDemoState {\n    userId: number;\n}\n\nconst simulateFetch = (userId: number): Promise<string> =>\n    new Promise((resolve) => {\n        setTimeout(() => {\n            const profiles: Record<number, string> = {\n                1: 'Alice Johnson — Senior Engineer',\n                2: 'Bob Smith — Product Manager',\n                3: 'Charlie Brown — Designer',\n            };\n            resolve(profiles[userId] || `User #${userId} — Unknown`);\n        }, 1500);\n    });\n\nconst asyncStore = create<AsyncDemoState>(() => ({ userId: 1 }));\nasyncStore.compute('profile', (state) => simulateFetch(state.userId), ['userId']);\nconst useAsyncDemo = createHook(asyncStore);\n\nconst asyncCode = `import { create, createHook } from 'fluxo-ui/store';\n\nconst asyncStore = create<{ userId: number }>(() => ({ userId: 1 }));\n\nasyncStore.compute(\n  'profile',\n  async (state) => {\n    const res = await fetch(\\`/api/users/\\${state.userId}\\`);\n    return res.json();\n  },\n  ['userId']\n);\n\nconst useStore = createHook(asyncStore);\n\nfunction UserProfile() {\n  const state = useStore() as any;\n  // state.profile       → the resolved value (undefined while loading)\n  // state.profileLoading → boolean (true while fetching)\n\n  if (state.profileLoading) return <p>Loading profile...</p>;\n  return <p>{state.profile}</p>;\n}`;\n\nconst AsyncComputeDemo: React.FC = () => {\n    const { isDark } = useStoryTheme();\n    const state = useAsyncDemo() as any;\n\n    return (\n        <div className=\"flex flex-col items-center gap-4 w-full max-w-md mx-auto\">\n            <div className={cn('text-sm', { 'text-gray-400': isDark, 'text-gray-500': !isDark })}>\n                Select a user to load their profile asynchronously\n            </div>\n            <div className=\"flex gap-2\">\n                {[1, 2, 3].map((id) => (\n                    <Button\n                        key={id}\n                        label={`User ${id}`}\n                        size=\"sm\"\n                        variant={state.userId === id ? 'default' : 'secondary'}\n                        onClick={() => asyncStore.setState({ userId: id })}\n                    />\n                ))}\n            </div>\n            <div\n                className={cn('w-full rounded-lg border p-4 text-center min-h-[60px] flex items-center justify-center', {\n                    'border-white/10 bg-white/5': isDark,\n                    'border-gray-200 bg-gray-50': !isDark,\n                })}\n            >\n                {state.profileLoading ? (\n                    <div className=\"flex items-center gap-2\">\n                        <svg\n                            className=\"animate-spin h-4 w-4 text-[var(--eui-primary)]\"\n                            xmlns=\"http://www.w3.org/2000/svg\"\n                            fill=\"none\"\n                            viewBox=\"0 0 24 24\"\n                        >\n                            <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"4\" />\n                            <path className=\"opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z\" />\n                        </svg>\n                        <span className={cn('text-sm', { 'text-gray-400': isDark, 'text-gray-500': !isDark })}>Loading profile...</span>\n                    </div>\n                ) : (\n                    <span className={cn('text-sm font-medium', { 'text-gray-200': isDark, 'text-gray-700': !isDark })}>\n                        {state.profile || 'No profile loaded'}\n                    </span>\n                )}\n            </div>\n        </div>\n    );\n};\n\nconst ComputedProperties: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo\n                title=\"Synchronous Computed Properties\"\n                description=\"Derived state that updates automatically when dependencies change\"\n                centered={false}\n            >\n                <div className=\"p-6\">\n                    <SyncUserCard />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={syncCode} language=\"tsx\" />\n            </div>\n\n            <div className=\"mt-8\">\n                <ComponentDemo\n                    title=\"Async Computed Properties\"\n                    description=\"Computed properties that resolve asynchronously with automatic loading state\"\n                    centered={false}\n                >\n                    <div className=\"p-6\">\n                        <AsyncComputeDemo />\n                    </div>\n                </ComponentDemo>\n                <div className=\"mt-4\">\n                    <CodeBlock code={asyncCode} language=\"tsx\" />\n                </div>\n            </div>\n        </>\n    );\n};\n\nexport default ComputedProperties;\n"
        }
      ],
      "middleware": [
        {
          "title": "AuthoringMiddleware",
          "code": "import cn from 'classnames';\nimport React from 'react';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\n\nconst contractCode = `// A middleware is just a function that takes the store and returns a (usually wrapped) store.\nimport type { Middleware, Store } from 'fluxo-ui/store';\n\nconst myMiddleware: Middleware<MyState> = (store: Store<MyState>) => {\n  // Inspect, wrap, or augment the store, then return it.\n  return store;\n};\n\nconst store = create<MyState>(() => initial, [myMiddleware]);\n`;\n\nconst wrapSetStateCode = `// Pattern 1: Wrap setState — useful for throttling, validating, transforming writes.\nconst upperCaseNames: Middleware<{ name: string }> = (store) => {\n  const original = store.setState;\n  store.setState = (next, ...rest) => {\n    if (typeof next !== 'function' && next?.name) next.name = next.name.toUpperCase();\n    return original(next as any, ...rest as [any, any?]);\n  };\n  return store;\n};\n`;\n\nconst subscribeCode = `// Pattern 2: Subscribe via store.on() — useful for logging, persistence, broadcasting.\nconst auditMiddleware: Middleware<any> = (store) => {\n  store.on('change', (state, { previous }) => {\n    track('state_changed', { previous, state });\n  });\n  return store;\n};\n`;\n\nconst augmentCode = `// Pattern 3: Augment the returned store with new methods — useful for undo/redo, optimistic, etc.\ninterface SnapshotStore<T> extends Store<T> {\n  snapshot: () => T;\n}\n\nconst snapshotMiddleware = <T,>(store: Store<T>): SnapshotStore<T> => {\n  return {\n    ...store,\n    snapshot: () => structuredClone(store.getState()),\n  };\n};\n`;\n\nconst orderCode = `// Order matters: middlewares wrap left-to-right.\n// The leftmost middleware sees user calls first; the rightmost is closest to the underlying store.\nconst store = create(() => initial, [\n  loggerMiddleware(),       // sees the original setState from the user\n  throttleMiddleware(100),  // throttles before the change reaches persist\n  persistMiddleware({ debounceMs: 200 }),\n]);\n`;\n\nconst AuthoringMiddleware: React.FC = () => {\n    const { isDark } = useStoryTheme();\n\n    return (\n        <ComponentDemo\n            title=\"Build Your Own Middleware\"\n            description=\"The middleware contract is one line. Three patterns cover almost every use case.\"\n            centered={false}\n        >\n            <div className=\"p-6 flex flex-col gap-5\">\n                <div>\n                    <h3 className={cn('text-base font-semibold mb-2', { 'text-gray-200': isDark, 'text-gray-800': !isDark })}>\n                        The contract\n                    </h3>\n                    <CodeBlock code={contractCode} language=\"ts\" />\n                </div>\n                <div>\n                    <h3 className={cn('text-base font-semibold mb-2', { 'text-gray-200': isDark, 'text-gray-800': !isDark })}>\n                        Pattern 1 — wrap setState\n                    </h3>\n                    <CodeBlock code={wrapSetStateCode} language=\"ts\" />\n                </div>\n                <div>\n                    <h3 className={cn('text-base font-semibold mb-2', { 'text-gray-200': isDark, 'text-gray-800': !isDark })}>\n                        Pattern 2 — subscribe via store.on()\n                    </h3>\n                    <CodeBlock code={subscribeCode} language=\"ts\" />\n                </div>\n                <div>\n                    <h3 className={cn('text-base font-semibold mb-2', { 'text-gray-200': isDark, 'text-gray-800': !isDark })}>\n                        Pattern 3 — augment the store\n                    </h3>\n                    <CodeBlock code={augmentCode} language=\"ts\" />\n                </div>\n                <div>\n                    <h3 className={cn('text-base font-semibold mb-2', { 'text-gray-200': isDark, 'text-gray-800': !isDark })}>\n                        Composition order\n                    </h3>\n                    <CodeBlock code={orderCode} language=\"ts\" />\n                </div>\n            </div>\n        </ComponentDemo>\n    );\n};\n\nexport default AuthoringMiddleware;\n"
        },
        {
          "title": "DebounceDemo",
          "code": "import cn from 'classnames';\nimport React, { useRef } from 'react';\nimport { TextInput } from '../../../components';\nimport { create, createHook } from '../../../store';\nimport { debounceMiddleware } from '../../../store/middlewares';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\n\ninterface SearchState {\n    query: string;\n    searchCount: number;\n}\n\nconst debouncedStore = create<SearchState>(() => ({ query: '', searchCount: 0 }), [debounceMiddleware(500)]);\nconst useDebouncedStore = createHook(debouncedStore);\n\nconst normalStore = create<SearchState>(() => ({ query: '', searchCount: 0 }));\nconst useNormalStore = createHook(normalStore);\n\nconst debounceCode = `import { create, createHook } from 'fluxo-ui/store';\nimport { debounceMiddleware } from 'fluxo-ui/store/middlewares';\n\nconst store = create<{ query: string }>(\n  () => ({ query: '' }),\n  [debounceMiddleware(500)]\n);\nconst useStore = createHook(store);\n\nfunction SearchInput() {\n  const { query } = useStore();\n  // State only updates 500ms after the user stops typing\n  return (\n    <TextInput\n      value={query}\n      onChange={(e) => store.setState({ query: e.target.value })}\n      placeholder=\"Type to search...\"\n    />\n  );\n}`;\n\nconst DebouncedPanel: React.FC<{ title: string; store: typeof debouncedStore; hook: typeof useDebouncedStore }> = ({\n    title,\n    store: s,\n    hook,\n}) => {\n    const { isDark } = useStoryTheme();\n    const state = hook();\n    const renderCount = useRef(0);\n    renderCount.current++;\n\n    return (\n        <div\n            className={cn('flex-1 rounded-lg border p-4', {\n                'border-white/10 bg-white/5': isDark,\n                'border-gray-200 bg-gray-50': !isDark,\n            })}\n        >\n            <div\n                className={cn('text-xs font-semibold uppercase tracking-wider mb-3', {\n                    'text-gray-400': isDark,\n                    'text-gray-500': !isDark,\n                })}\n            >\n                {title}\n            </div>\n            <TextInput\n                value={state.query}\n                onChange={(e) => s.setState({ query: e.target.value, searchCount: s.getState().searchCount + 1 })}\n                placeholder=\"Type rapidly...\"\n            />\n            <div\n                className={cn('mt-3 text-sm space-y-1', {\n                    'text-gray-300': isDark,\n                    'text-gray-600': !isDark,\n                })}\n            >\n                <div>\n                    Updates: <span className=\"font-bold text-[var(--eui-primary)]\">{state.searchCount}</span>\n                </div>\n                <div>\n                    Renders: <span className=\"font-bold text-[var(--eui-primary)]\">{renderCount.current}</span>\n                </div>\n            </div>\n        </div>\n    );\n};\n\nconst DebounceDemo: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo\n                title=\"Debounce\"\n                description=\"Delay state updates until input activity stops. Compare debounced vs immediate updates.\"\n            >\n                <div className=\"flex gap-4 flex-col sm:flex-row w-full\">\n                    <DebouncedPanel title=\"With Debounce (500ms)\" store={debouncedStore} hook={useDebouncedStore} />\n                    <DebouncedPanel title=\"Without Debounce\" store={normalStore} hook={useNormalStore} />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={debounceCode} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default DebounceDemo;\n"
        },
        {
          "title": "LoggingDemo",
          "code": "import cn from 'classnames';\nimport React, { useState } from 'react';\nimport { Button } from '../../../components';\nimport { create, createHook } from '../../../store';\nimport { loggerMiddleware } from '../../../store/middlewares';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\n\ninterface LogState {\n    count: number;\n    label: string;\n}\n\nconst logStore = create<LogState>(() => ({ count: 0, label: 'Hello' }), [loggerMiddleware()]);\nconst useLogStore = createHook(logStore);\n\nconst loggingCode = `import { create, createHook } from 'fluxo-ui/store';\nimport { loggerMiddleware } from 'fluxo-ui/store/middlewares';\n\nconst store = create<{ count: number; label: string }>(\n  () => ({ count: 0, label: 'Hello' }),\n  [loggerMiddleware()]\n);\nconst useStore = createHook(store);\n\n// With predicate — only log when count changes\nconst store2 = create<{ count: number }>(\n  () => ({ count: 0 }),\n  [loggerMiddleware((state, previous) => state.count !== previous?.count)]\n);\n\n// Open browser DevTools console to see logs`;\n\nconst LoggingDemo: React.FC = () => {\n    const { isDark } = useStoryTheme();\n    const { count, label } = useLogStore();\n    const [showHint, setShowHint] = useState(true);\n\n    return (\n        <>\n            <ComponentDemo title=\"Logger\" description=\"Logs state changes to the browser console with loggerMiddleware\">\n                <div className=\"flex flex-col items-center gap-4\">\n                    {showHint && (\n                        <div\n                            className={cn('text-xs px-4 py-2 rounded-lg flex items-center gap-2', {\n                                'bg-blue-500/10 text-blue-400 border border-blue-500/20': isDark,\n                                'bg-blue-50 text-blue-700 border border-blue-200': !isDark,\n                            })}\n                        >\n                            Open browser DevTools console to see the logs\n                            <Button label=\"×\" size=\"xs\" layout=\"plain\" onClick={() => setShowHint(false)} />\n                        </div>\n                    )}\n                    <div className={cn('text-sm', { 'text-gray-300': isDark, 'text-gray-700': !isDark })}>\n                        Count: <span className=\"font-bold text-[var(--eui-primary)]\">{count}</span>\n                        {' · '}\n                        Label: <span className=\"font-bold text-[var(--eui-primary)]\">{label}</span>\n                    </div>\n                    <div className=\"flex gap-2\">\n                        <Button label=\"Increment\" size=\"sm\" onClick={() => logStore.setState((s) => ({ count: s.count + 1 }))} />\n                        <Button\n                            label=\"Change Label\"\n                            size=\"sm\"\n                            onClick={() => logStore.setState({ label: label === 'Hello' ? 'World' : 'Hello' })}\n                        />\n                        <Button label=\"Reset\" size=\"sm\" variant=\"secondary\" onClick={() => logStore.reset()} />\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={loggingCode} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default LoggingDemo;\n"
        },
        {
          "title": "OptimisticDemo",
          "code": "import cn from 'classnames';\nimport React, { useRef, useState } from 'react';\nimport { Button } from '../../../components';\nimport { create, createHook } from '../../../store';\nimport { optimisticMiddleware, OptimisticStore } from '../../../store/middlewares';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\n\ninterface LikeState {\n    likes: number;\n    serverLikes: number;\n}\n\nconst fakeServer = (failureRate: { value: number }, latency: number) =>\n    new Promise<void>((resolve, reject) => {\n        setTimeout(() => {\n            if (Math.random() < failureRate.value) {\n                reject(new Error('Server rejected the change'));\n            } else {\n                resolve();\n            }\n        }, latency);\n    });\n\nconst failureRate = { value: 0.4 };\n\nconst optimisticStore = create<LikeState>(() => ({ likes: 0, serverLikes: 0 }), [\n    optimisticMiddleware<LikeState>({\n        commit: async (next) => {\n            await fakeServer(failureRate, 600);\n            optimisticStore.setState({ serverLikes: next.likes });\n        },\n    }),\n]) as OptimisticStore<LikeState>;\n\nconst useOptimistic = createHook(optimisticStore);\n\nconst code = `import { create } from 'fluxo-ui/store';\nimport { optimisticMiddleware } from 'fluxo-ui/store/middlewares';\n\nconst store = create<LikeState>(\n  () => ({ likes: 0, serverLikes: 0 }),\n  [optimisticMiddleware<LikeState>({\n    commit: async (next) => {\n      // Send to server. If this rejects, the state automatically rolls back.\n      await fetch('/api/likes', { method: 'POST', body: JSON.stringify(next) });\n      store.setState({ serverLikes: next.likes });\n    },\n    onRollback: (prev, attempted, error) => {\n      showSnackbar({ severity: 'error', message: 'Save failed — reverted' });\n    },\n  })]\n);\n\n// Use store.optimistic() instead of setState() for changes that need server confirmation\nstore.optimistic((s) => ({ likes: s.likes + 1 }));\n`;\n\nconst OptimisticDemo: React.FC = () => {\n    const { isDark } = useStoryTheme();\n    const state = useOptimistic();\n    const [log, setLog] = useState<string[]>([]);\n    const counter = useRef(0);\n\n    const like = () => {\n        counter.current++;\n        const id = counter.current;\n        optimisticStore.optimistic((s) => ({ likes: s.likes + 1 }));\n        setLog((prev) => [...prev.slice(-9), `#${id} optimistic +1 (sending...)`]);\n        setTimeout(() => {\n            const synced = optimisticStore.getState();\n            const ok = synced.likes === synced.serverLikes;\n            setLog((prev) => [...prev.slice(-9), `#${id} ${ok ? 'committed' : 'rolled back'} → likes=${synced.likes}`]);\n        }, 700);\n    };\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Optimistic Updates with Auto-Rollback\"\n                description=\"Click +1 — UI updates immediately. A simulated server fails ~40% of the time. On failure the change rolls back automatically.\"\n            >\n                <div className=\"flex flex-col items-center gap-4 w-full max-w-md\">\n                    <div className=\"flex gap-8\">\n                        <div className=\"text-center\">\n                            <div\n                                className={cn('text-xs uppercase tracking-wide mb-1', {\n                                    'text-gray-500': isDark,\n                                    'text-gray-400': !isDark,\n                                })}\n                            >\n                                Optimistic\n                            </div>\n                            <div className=\"text-4xl font-bold tabular-nums text-[var(--eui-primary)]\">{state.likes}</div>\n                        </div>\n                        <div className=\"text-center\">\n                            <div\n                                className={cn('text-xs uppercase tracking-wide mb-1', {\n                                    'text-gray-500': isDark,\n                                    'text-gray-400': !isDark,\n                                })}\n                            >\n                                Server\n                            </div>\n                            <div\n                                className={cn('text-4xl font-bold tabular-nums', {\n                                    'text-emerald-400': isDark,\n                                    'text-emerald-600': !isDark,\n                                })}\n                            >\n                                {state.serverLikes}\n                            </div>\n                        </div>\n                    </div>\n                    <div className=\"flex gap-2 flex-wrap justify-center\">\n                        <Button label=\"+1 Like (optimistic)\" size=\"sm\" onClick={like} />\n                        <Button\n                            label=\"Lower failure rate\"\n                            size=\"sm\"\n                            variant=\"secondary\"\n                            onClick={() => {\n                                failureRate.value = 0.05;\n                                setLog((prev) => [...prev.slice(-9), `failure rate → 5%`]);\n                            }}\n                        />\n                        <Button\n                            label=\"Reset\"\n                            size=\"sm\"\n                            variant=\"secondary\"\n                            onClick={() => optimisticStore.setState({ likes: 0, serverLikes: 0 }, true)}\n                        />\n                    </div>\n                    <div\n                        className={cn('w-full text-xs font-mono p-3 rounded max-h-40 overflow-auto', {\n                            'bg-black/30 text-gray-300': isDark,\n                            'bg-gray-100 text-gray-700': !isDark,\n                        })}\n                    >\n                        {log.length === 0 && <div className=\"italic opacity-60\">Click +1 to see commits and rollbacks</div>}\n                        {log.map((line, i) => (\n                            <div key={i}>{line}</div>\n                        ))}\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default OptimisticDemo;\n"
        },
        {
          "title": "SyncDemo",
          "code": "import cn from 'classnames';\nimport React from 'react';\nimport { Button } from '../../../components';\nimport { create, createHook } from '../../../store';\nimport { broadcastChannelTransport, syncMiddleware } from '../../../store/middlewares';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\n\ninterface SyncState {\n    count: number;\n    lastUpdatedBy: string;\n}\n\nconst tabId = Math.random().toString(36).slice(2, 6).toUpperCase();\n\nconst syncStore = create<SyncState>(() => ({ count: 0, lastUpdatedBy: 'none' }), [\n    syncMiddleware<SyncState>({\n        transport: broadcastChannelTransport('fluxo-ui-demo-sync'),\n        resolve: 'merge',\n    }),\n]);\nconst useSync = createHook(syncStore);\n\nconst code = `import { create } from 'fluxo-ui/store';\nimport {\n  syncMiddleware,\n  broadcastChannelTransport,\n  webSocketTransport,\n  storageEventTransport,\n} from 'fluxo-ui/store/middlewares';\n\nconst store = create<SyncState>(() => ({ count: 0 }), [\n  syncMiddleware<SyncState>({\n    transport: broadcastChannelTransport('my-app'),       // or webSocketTransport('wss://...')\n    resolve: 'merge',                                      // 'remote-wins' | 'local-wins' | 'merge' | (local, remote) => Partial<T>\n  }),\n]);\n\n// Implement your own SyncTransport to use any other channel:\n// { send(msg), onReceive(handler): unsubscribe, close?() }\n`;\n\nconst SyncDemo: React.FC = () => {\n    const { isDark } = useStoryTheme();\n    const state = useSync();\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Sync Middleware (Pluggable Transport)\"\n                description=\"syncMiddleware abstracts the transport. Below uses BroadcastChannel; the same store can swap to WebSocket or a custom transport without changing call sites. Open the page in two tabs to see updates flow through.\"\n            >\n                <div className=\"flex flex-col items-center gap-4 w-full max-w-sm mx-auto\">\n                    <div\n                        className={cn('text-xs font-mono px-2 py-1 rounded', {\n                            'bg-white/10 text-gray-400': isDark,\n                            'bg-gray-100 text-gray-500': !isDark,\n                        })}\n                    >\n                        Tab ID: {tabId}\n                    </div>\n                    <div className=\"text-4xl font-bold tabular-nums text-[var(--eui-primary)]\">{state.count}</div>\n                    {state.lastUpdatedBy !== 'none' && (\n                        <div className={cn('text-xs', { 'text-gray-400': isDark, 'text-gray-500': !isDark })}>\n                            Last updated by: {state.lastUpdatedBy === tabId ? 'this tab' : `tab ${state.lastUpdatedBy}`}\n                        </div>\n                    )}\n                    <div className=\"flex gap-2\">\n                        <Button\n                            label=\"+1\"\n                            size=\"sm\"\n                            onClick={() => syncStore.setState((s) => ({ count: s.count + 1, lastUpdatedBy: tabId }))}\n                        />\n                        <Button\n                            label=\"+5\"\n                            size=\"sm\"\n                            onClick={() => syncStore.setState((s) => ({ count: s.count + 5, lastUpdatedBy: tabId }))}\n                        />\n                        <Button\n                            label=\"Reset\"\n                            size=\"sm\"\n                            variant=\"secondary\"\n                            onClick={() => syncStore.setState({ count: 0, lastUpdatedBy: tabId })}\n                        />\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default SyncDemo;\n"
        },
        {
          "title": "ThrottleDemo",
          "code": "import cn from 'classnames';\nimport React, { useRef } from 'react';\nimport { Button } from '../../../components';\nimport { create, createHook } from '../../../store';\nimport { throttleMiddleware } from '../../../store/middlewares';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\n\ninterface ThrottleState {\n    value: number;\n}\n\nconst throttledStore = create<ThrottleState>(() => ({ value: 0 }), [throttleMiddleware(500)]);\nconst useThrottledStore = createHook(throttledStore);\n\nconst normalStore = create<ThrottleState>(() => ({ value: 0 }));\nconst useNormalStore = createHook(normalStore);\n\nconst throttleCode = `import { create, createHook } from 'fluxo-ui/store';\nimport { throttleMiddleware } from 'fluxo-ui/store/middlewares';\n\n// Updates are batched within a 500ms window\nconst store = create<{ value: number }>(\n  () => ({ value: 0 }),\n  [throttleMiddleware(500)]\n);\nconst useStore = createHook(store);\n\nfunction ThrottleDemo() {\n  const { value } = useStore();\n\n  const handleRapidClicks = () => {\n    // These rapid calls are merged and applied once after 500ms\n    for (let i = 0; i < 10; i++) {\n      store.setState((s) => ({ value: s.value + 1 }));\n    }\n  };\n\n  return (\n    <div>\n      <span>Value: {value}</span>\n      <Button label=\"Rapid +10\" onClick={handleRapidClicks} />\n    </div>\n  );\n}`;\n\nconst ThrottleDemo: React.FC = () => {\n    const { isDark } = useStoryTheme();\n    const throttledRenders = useRef(0);\n    const normalRenders = useRef(0);\n\n    throttledRenders.current++;\n    const { value: throttledValue } = useThrottledStore();\n\n    normalRenders.current++;\n    const { value: normalValue } = useNormalStore();\n\n    const handleRapidThrottled = () => {\n        for (let i = 0; i < 10; i++) {\n            throttledStore.setState((s) => ({ value: s.value + 1 }));\n        }\n    };\n\n    const handleRapidNormal = () => {\n        for (let i = 0; i < 10; i++) {\n            normalStore.setState((s) => ({ value: s.value + 1 }));\n        }\n    };\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Throttle\"\n                description=\"Batch rapid state updates within a time window using throttleMiddleware\"\n                centered={false}\n            >\n                <div className=\"p-6\">\n                    <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n                        <div\n                            className={cn('rounded-lg p-4 border text-center', {\n                                'border-white/10 bg-white/5': isDark,\n                                'border-gray-200 bg-gray-50': !isDark,\n                            })}\n                        >\n                            <div\n                                className={cn('text-xs uppercase tracking-wide mb-2 font-semibold', {\n                                    'text-gray-500': isDark,\n                                    'text-gray-400': !isDark,\n                                })}\n                            >\n                                With Throttle (500ms)\n                            </div>\n                            <div className=\"text-3xl font-bold tabular-nums text-[var(--eui-primary)] mb-1\">{throttledValue}</div>\n                            <div className={cn('text-xs mb-3', { 'text-gray-500': isDark, 'text-gray-400': !isDark })}>\n                                Renders: {throttledRenders.current}\n                            </div>\n                            <Button label=\"Rapid +10\" size=\"sm\" onClick={handleRapidThrottled} />\n                        </div>\n                        <div\n                            className={cn('rounded-lg p-4 border text-center', {\n                                'border-white/10 bg-white/5': isDark,\n                                'border-gray-200 bg-gray-50': !isDark,\n                            })}\n                        >\n                            <div\n                                className={cn('text-xs uppercase tracking-wide mb-2 font-semibold', {\n                                    'text-gray-500': isDark,\n                                    'text-gray-400': !isDark,\n                                })}\n                            >\n                                Without Throttle\n                            </div>\n                            <div className=\"text-3xl font-bold tabular-nums text-[var(--eui-primary)] mb-1\">{normalValue}</div>\n                            <div className={cn('text-xs mb-3', { 'text-gray-500': isDark, 'text-gray-400': !isDark })}>\n                                Renders: {normalRenders.current}\n                            </div>\n                            <Button label=\"Rapid +10\" size=\"sm\" onClick={handleRapidNormal} />\n                        </div>\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={throttleCode} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default ThrottleDemo;\n"
        },
        {
          "title": "UndoRedoDemo",
          "code": "import React from 'react';\nimport { Button } from '../../../components';\nimport { create, createHook } from '../../../store';\nimport type { UndoRedoStateProps, UndoRedoStore } from '../../../store/middlewares';\nimport { undoRedoMiddleware } from '../../../store/middlewares';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\n\ninterface UndoState {\n    value: number;\n}\n\nconst undoStore = create<UndoState>(() => ({ value: 0 }), [undoRedoMiddleware({ maxHistorySize: 20 })]);\nconst useUndoStore = createHook<UndoState, UndoState & UndoRedoStateProps>(undoStore);\nconst typedStore = undoStore as UndoRedoStore<UndoState>;\n\nconst undoRedoCode = `import { create, createHook } from 'fluxo-ui/store';\nimport { undoRedoMiddleware } from 'fluxo-ui/store/middlewares';\nimport type { UndoRedoStateProps, UndoRedoStore } from 'fluxo-ui/store/middlewares';\n\ninterface CounterState { value: number; }\n\nconst store = create<CounterState>(\n  () => ({ value: 0 }),\n  [undoRedoMiddleware({ maxHistorySize: 20 })]\n);\nconst useStore = createHook<CounterState, CounterState & UndoRedoStateProps>(store);\nconst typedStore = store as UndoRedoStore<CounterState>;\n\nfunction UndoDemo() {\n  const { value, canUndo, canRedo } = useStore();\n\n  return (\n    <div>\n      <span>{value}</span>\n      <Button label=\"+1\"\n        onClick={() => store.setState(s => ({ value: s.value + 1 }))} />\n      <Button label=\"+5\"\n        onClick={() => store.setState(s => ({ value: s.value + 5 }))} />\n      <Button label=\"Undo\" disabled={!canUndo}\n        onClick={() => typedStore.undo()} />\n      <Button label=\"Redo\" disabled={!canRedo}\n        onClick={() => typedStore.redo()} />\n    </div>\n  );\n}`;\n\nconst UndoRedoDemo: React.FC = () => {\n    const { value, canUndo, canRedo } = useUndoStore();\n\n    return (\n        <>\n            <ComponentDemo title=\"Undo / Redo\" description=\"Track state history and navigate back and forth with undoRedoMiddleware\">\n                <div className=\"flex flex-col items-center gap-4\">\n                    <div className=\"text-4xl font-bold tabular-nums text-[var(--eui-primary)]\">{value}</div>\n                    <div className=\"flex gap-2 flex-wrap justify-center\">\n                        <Button label=\"+1\" size=\"sm\" onClick={() => undoStore.setState((s) => ({ value: s.value + 1 }))} />\n                        <Button label=\"+5\" size=\"sm\" onClick={() => undoStore.setState((s) => ({ value: s.value + 5 }))} />\n                        <Button label=\"Undo\" size=\"sm\" variant=\"secondary\" disabled={!canUndo} onClick={() => typedStore.undo()} />\n                        <Button label=\"Redo\" size=\"sm\" variant=\"secondary\" disabled={!canRedo} onClick={() => typedStore.redo()} />\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={undoRedoCode} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default UndoRedoDemo;\n"
        }
      ],
      "model": [
        {
          "title": "BasicCRUD",
          "code": "import cn from 'classnames';\nimport React, { useCallback, useMemo, useState } from 'react';\nimport { Button, TextInput } from '../../../components';\nimport { createItemHook, createModel } from '../../../store';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\n\ninterface Todo {\n    id: number;\n    title: string;\n    completed: boolean;\n}\n\nlet nextTodoId = 1;\n\nconst todoFactory = createModel<Todo>({\n    nextId: () => nextTodoId++,\n    createWithDefaults: (id) => ({\n        id,\n        title: '',\n        completed: false,\n    }),\n    selectId: (state) => state.id,\n});\n\nconst code = `import { createModel, createItemHook } from 'fluxo-ui/store';\n\ninterface Todo {\n    id: number;\n    title: string;\n    completed: boolean;\n}\n\nlet nextTodoId = 1;\n\nconst todoFactory = createModel<Todo>({\n    nextId: () => nextTodoId++,\n    createWithDefaults: (id) => ({\n        id, title: '', completed: false,\n    }),\n    selectId: (state) => state.id,\n});\n\n// Create a new todo\nconst store = todoFactory.create({ title: 'My Task' });\n\n// Read state\nconst state = store.getState(); // { id: 1, title: 'My Task', completed: false }\n\n// Update state\nstore.setState({ completed: true });\n\n// Delete / destroy\nstore.destroy();\n\n// React hook for a single item\nconst useItem = createItemHook(store);\nfunction TodoItem() {\n    const todo = useItem();\n    return <span>{todo.title}</span>;\n}`;\n\ninterface TodoItemProps {\n    todoId: number;\n    onDelete: (id: number) => void;\n}\n\nconst TodoItem: React.FC<TodoItemProps> = ({ todoId, onDelete }) => {\n    const { isDark } = useStoryTheme();\n    const store = todoFactory.get(todoId);\n    const useItem = useMemo(() => (store ? createItemHook(store) : null), [store]);\n    const todo = useItem?.() as\n        | (Todo & { id: number; isStale: boolean; isLoading: boolean; isSaving: boolean; isDeleting: boolean })\n        | undefined;\n\n    const handleToggle = useCallback(() => {\n        store?.setState({ completed: !todo?.completed });\n    }, [store, todo?.completed]);\n\n    if (!todo) return null;\n\n    return (\n        <div\n            className={cn('flex items-center gap-3 px-4 py-3 rounded-lg border transition-all', {\n                'border-white/10 bg-white/5': isDark,\n                'border-gray-200 bg-white': !isDark,\n            })}\n        >\n            <button\n                onClick={handleToggle}\n                className={cn('w-5 h-5 rounded border-2 flex items-center justify-center transition-colors shrink-0', {\n                    'border-green-500 bg-green-500': todo.completed,\n                    'border-gray-400 hover:border-blue-400': !todo.completed && !isDark,\n                    'border-gray-600 hover:border-blue-400': !todo.completed && isDark,\n                })}\n                aria-label={todo.completed ? 'Mark incomplete' : 'Mark complete'}\n            >\n                {todo.completed && (\n                    <svg className=\"w-3 h-3 text-white\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={3}>\n                        <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M5 13l4 4L19 7\" />\n                    </svg>\n                )}\n            </button>\n            <span\n                className={cn('flex-1 text-sm', {\n                    'line-through text-gray-500': todo.completed,\n                    'text-gray-200': !todo.completed && isDark,\n                    'text-gray-700': !todo.completed && !isDark,\n                })}\n            >\n                {todo.title}\n            </span>\n            <Button\n                label=\"Delete\"\n                size=\"xs\"\n                variant=\"danger\"\n                layout=\"plain\"\n                onClick={() => {\n                    store?.destroy();\n                    onDelete(todoId);\n                }}\n            />\n        </div>\n    );\n};\n\nconst BasicCRUD: React.FC = () => {\n    const [todoIds, setTodoIds] = useState<number[]>([]);\n    const [newTitle, setNewTitle] = useState('');\n\n    const handleAdd = () => {\n        if (!newTitle.trim()) return;\n        const store = todoFactory.create({ title: newTitle.trim() });\n        setTodoIds((prev) => [...prev, store.id]);\n        setNewTitle('');\n    };\n\n    const handleDelete = (id: number) => {\n        setTodoIds((prev) => prev.filter((tid) => tid !== id));\n    };\n\n    const handleKeyDown = (e: React.KeyboardEvent) => {\n        if (e.key === 'Enter') handleAdd();\n    };\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Basic CRUD Operations\"\n                description=\"Create, read, update, and delete todos using createModel\"\n                centered={false}\n            >\n                <div className=\"w-full max-w-lg mx-auto p-4\">\n                    <div className=\"flex gap-2 mb-4\">\n                        <TextInput\n                            value={newTitle}\n                            onChange={(e) => setNewTitle(e.target.value)}\n                            onKeyDown={handleKeyDown}\n                            placeholder=\"Add a new todo...\"\n                            className=\"flex-1\"\n                        />\n                        <Button label=\"Add\" size=\"sm\" onClick={handleAdd} />\n                    </div>\n                    <div className=\"space-y-2\">\n                        {todoIds.length === 0 && <p className=\"text-sm text-center py-6 text-gray-400\">No todos yet. Add one above.</p>}\n                        {todoIds.map((id) => (\n                            <TodoItem key={id} todoId={id} onDelete={handleDelete} />\n                        ))}\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default BasicCRUD;\n"
        }
      ],
      "slice": [
        {
          "title": "BasicSlice",
          "code": "import cn from 'classnames';\nimport React, { useRef } from 'react';\nimport { Button } from '../../../components';\nimport { combineSlices, createHook, createSlice } from '../../../store';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\n\ninterface AuthState {\n    user: string;\n    role: 'admin' | 'editor' | 'viewer';\n}\n\ninterface CartState {\n    items: number;\n    total: number;\n}\n\nconst authSlice = createSlice<AuthState>('auth', () => ({ user: 'Alice', role: 'admin' }));\nconst cartSlice = createSlice<CartState>('cart', () => ({ items: 0, total: 0 }));\n\nconst appStore = combineSlices({ auth: authSlice, cart: cartSlice });\n\nconst useApp = createHook(appStore);\nconst useAuth = createHook(authSlice);\nconst useCart = createHook(cartSlice);\n\nconst code = `import { combineSlices, createHook, createSlice } from 'fluxo-ui/store';\n\nconst authSlice = createSlice<AuthState>('auth', () => ({ user: 'Alice', role: 'admin' }));\nconst cartSlice = createSlice<CartState>('cart', () => ({ items: 0, total: 0 }));\n\nconst appStore = combineSlices({ auth: authSlice, cart: cartSlice });\n\n// Each slice has a hook of its own — selectors only see the slice's branch\nconst useAuth = createHook(authSlice);\nconst useCart = createHook(cartSlice);\n\n// And the combined store has a hook for the whole tree\nconst useApp = createHook(appStore);\n\n// Direct slice writes are reflected in the combined store and vice versa.\nauthSlice.setState({ role: 'editor' });           // appStore.getState().auth.role === 'editor'\nappStore.setState((s) => ({ cart: { ...s.cart, items: s.cart.items + 1 } }));  // cartSlice subscribers fire\n`;\n\nconst AuthCard: React.FC = () => {\n    const { isDark } = useStoryTheme();\n    const renderCount = useRef(0);\n    renderCount.current++;\n    const auth = useAuth();\n\n    const cycleRole = () => {\n        const next: AuthState['role'] = auth.role === 'admin' ? 'editor' : auth.role === 'editor' ? 'viewer' : 'admin';\n        authSlice.setState({ role: next });\n    };\n\n    return (\n        <div className={cn('rounded-lg p-4 border', { 'border-white/10 bg-white/5': isDark, 'border-gray-200 bg-gray-50': !isDark })}>\n            <div className=\"flex items-center justify-between mb-2\">\n                <div className={cn('text-xs uppercase tracking-wide font-semibold', { 'text-gray-500': isDark, 'text-gray-400': !isDark })}>\n                    Auth Slice (useAuth)\n                </div>\n                <div\n                    className={cn('text-xs px-2 py-0.5 rounded font-mono', {\n                        'bg-amber-500/20 text-amber-400': isDark,\n                        'bg-amber-100 text-amber-700': !isDark,\n                    })}\n                >\n                    renders: {renderCount.current}\n                </div>\n            </div>\n            <div className={cn('text-sm mb-1', { 'text-gray-300': isDark, 'text-gray-700': !isDark })}>\n                User: <span className=\"font-medium text-[var(--eui-primary)]\">{auth.user}</span>\n            </div>\n            <div className={cn('text-sm mb-3', { 'text-gray-300': isDark, 'text-gray-700': !isDark })}>\n                Role: <span className=\"font-medium text-[var(--eui-primary)]\">{auth.role}</span>\n            </div>\n            <Button label=\"Cycle Role (slice write)\" size=\"xs\" onClick={cycleRole} />\n        </div>\n    );\n};\n\nconst CartCard: React.FC = () => {\n    const { isDark } = useStoryTheme();\n    const renderCount = useRef(0);\n    renderCount.current++;\n    const cart = useCart();\n\n    const addItem = () => {\n        cartSlice.setState((s) => ({ items: s.items + 1, total: s.total + 9.99 }));\n    };\n\n    return (\n        <div className={cn('rounded-lg p-4 border', { 'border-white/10 bg-white/5': isDark, 'border-gray-200 bg-gray-50': !isDark })}>\n            <div className=\"flex items-center justify-between mb-2\">\n                <div className={cn('text-xs uppercase tracking-wide font-semibold', { 'text-gray-500': isDark, 'text-gray-400': !isDark })}>\n                    Cart Slice (useCart)\n                </div>\n                <div\n                    className={cn('text-xs px-2 py-0.5 rounded font-mono', {\n                        'bg-amber-500/20 text-amber-400': isDark,\n                        'bg-amber-100 text-amber-700': !isDark,\n                    })}\n                >\n                    renders: {renderCount.current}\n                </div>\n            </div>\n            <div className={cn('text-sm mb-1', { 'text-gray-300': isDark, 'text-gray-700': !isDark })}>\n                Items: <span className=\"font-medium text-[var(--eui-primary)]\">{cart.items}</span>\n            </div>\n            <div className={cn('text-sm mb-3', { 'text-gray-300': isDark, 'text-gray-700': !isDark })}>\n                Total: <span className=\"font-medium text-[var(--eui-primary)]\">${cart.total.toFixed(2)}</span>\n            </div>\n            <Button label=\"Add Item (slice write)\" size=\"xs\" onClick={addItem} />\n        </div>\n    );\n};\n\nconst CombinedView: React.FC = () => {\n    const { isDark } = useStoryTheme();\n    const renderCount = useRef(0);\n    renderCount.current++;\n    const state = useApp();\n\n    const writeViaCombined = () => {\n        appStore.setState((s) => ({\n            auth: { ...s.auth, user: s.auth.user === 'Alice' ? 'Bob' : 'Alice' },\n            cart: { ...s.cart, items: s.cart.items + 5, total: s.cart.total + 49.95 },\n        }));\n    };\n\n    return (\n        <div className={cn('rounded-lg p-4 border', { 'border-white/10 bg-white/5': isDark, 'border-gray-200 bg-gray-50': !isDark })}>\n            <div className=\"flex items-center justify-between mb-2\">\n                <div className={cn('text-xs uppercase tracking-wide font-semibold', { 'text-gray-500': isDark, 'text-gray-400': !isDark })}>\n                    Combined Store (useApp)\n                </div>\n                <div\n                    className={cn('text-xs px-2 py-0.5 rounded font-mono', {\n                        'bg-amber-500/20 text-amber-400': isDark,\n                        'bg-amber-100 text-amber-700': !isDark,\n                    })}\n                >\n                    renders: {renderCount.current}\n                </div>\n            </div>\n            <pre\n                className={cn('text-xs font-mono p-3 rounded mb-3 overflow-auto', {\n                    'bg-black/30 text-gray-300': isDark,\n                    'bg-gray-100 text-gray-700': !isDark,\n                })}\n            >\n                {JSON.stringify(state, null, 2)}\n            </pre>\n            <Button label=\"Write Both Slices (combined write)\" size=\"xs\" onClick={writeViaCombined} />\n        </div>\n    );\n};\n\nconst BasicSlice: React.FC = () => {\n    return (\n        <>\n            <ComponentDemo\n                title=\"Basic Slices\"\n                description=\"Two slices (auth, cart) composed into one combined store. Writes from either side flow to the other automatically.\"\n                centered={false}\n            >\n                <div className=\"p-6 flex flex-col gap-4\">\n                    <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n                        <AuthCard />\n                        <CartCard />\n                    </div>\n                    <CombinedView />\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default BasicSlice;\n"
        },
        {
          "title": "BidirectionalSync",
          "code": "import cn from 'classnames';\nimport React, { useEffect, useRef, useState } from 'react';\nimport { Button } from '../../../components';\nimport { combineSlices, createSlice } from '../../../store';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\n\ninterface CounterState {\n    value: number;\n}\n\ninterface SettingsState {\n    theme: 'light' | 'dark';\n    debug: boolean;\n}\n\nconst counterSlice = createSlice<CounterState>('counter', () => ({ value: 0 }));\nconst settingsSlice = createSlice<SettingsState>('settings', () => ({ theme: 'light', debug: false }));\n\nconst syncStore = combineSlices({ counter: counterSlice, settings: settingsSlice });\n\nconst code = `import { combineSlices, createSlice } from 'fluxo-ui/store';\n\nconst counterSlice = createSlice<CounterState>('counter', () => ({ value: 0 }));\nconst settingsSlice = createSlice<SettingsState>('settings', () => ({ theme: 'light', debug: false }));\n\nconst syncStore = combineSlices({ counter: counterSlice, settings: settingsSlice });\n\n// Slice-level path subscription — only fires for this slice's branch\ncounterSlice.on('change', 'value', (s) => console.log('[counter slice] value =', s.value));\n\n// Combined-level path subscription — fully-qualified path including the slice key\nsyncStore.on('change', 'counter.value', (s) => console.log('[combined] counter.value =', s.counter.value));\nsyncStore.on('change', 'settings.theme', (s) => console.log('[combined] settings.theme =', s.settings.theme));\n\n// Either write style triggers BOTH subscriptions:\ncounterSlice.setState({ value: 1 });             // slice direct\nsyncStore.setState((s) => ({ counter: { ...s.counter, value: 2 } })); // combined direct\n`;\n\nconst BidirectionalSync: React.FC = () => {\n    const { isDark } = useStoryTheme();\n    const [logs, setLogs] = useState<string[]>([]);\n    const counterRender = useRef(0);\n    const combinedRender = useRef(0);\n\n    useEffect(() => {\n        const unsub1 = counterSlice.on('change', 'value', (s) => {\n            counterRender.current++;\n            setLogs((prev) => [...prev.slice(-19), `[counter slice] value=${s.value}`]);\n        });\n        const unsub2 = settingsSlice.on('change', 'theme', (s) => {\n            setLogs((prev) => [...prev.slice(-19), `[settings slice] theme=${s.theme}`]);\n        });\n        const unsub3 = syncStore.on('change', 'counter.value', (s) => {\n            combinedRender.current++;\n            setLogs((prev) => [...prev.slice(-19), `[combined] counter.value=${s.counter.value}`]);\n        });\n        const unsub4 = syncStore.on('change', 'settings.theme', (s) => {\n            setLogs((prev) => [...prev.slice(-19), `[combined] settings.theme=${s.settings.theme}`]);\n        });\n        const unsub5 = syncStore.on('change', 'settings.debug', (s) => {\n            setLogs((prev) => [...prev.slice(-19), `[combined] settings.debug=${s.settings.debug}`]);\n        });\n        return () => {\n            unsub1();\n            unsub2();\n            unsub3();\n            unsub4();\n            unsub5();\n        };\n    }, []);\n\n    const sliceWrite = () => counterSlice.setState((s) => ({ value: s.value + 1 }));\n    const combinedWrite = () =>\n        syncStore.setState((s) => ({\n            counter: { ...s.counter, value: s.counter.value + 1 },\n        }));\n    const settingsSliceWrite = () =>\n        settingsSlice.setState((s) => ({ theme: s.theme === 'light' ? 'dark' : 'light' }));\n    const settingsCombinedWrite = () =>\n        syncStore.setState((s) => ({ settings: { ...s.settings, debug: !s.settings.debug } }));\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Bidirectional Sync\"\n                description=\"Slice subscribers and combined-store subscribers both fire on every change, no matter which side wrote.\"\n                centered={false}\n            >\n                <div className=\"p-6 flex flex-col gap-4\">\n                    <div\n                        className={cn('rounded-lg p-4 border flex flex-wrap gap-2', {\n                            'border-white/10 bg-white/5': isDark,\n                            'border-gray-200 bg-gray-50': !isDark,\n                        })}\n                    >\n                        <Button label=\"counter via slice\" size=\"sm\" onClick={sliceWrite} />\n                        <Button label=\"counter via combined\" size=\"sm\" variant=\"secondary\" onClick={combinedWrite} />\n                        <Button label=\"theme via slice\" size=\"sm\" onClick={settingsSliceWrite} />\n                        <Button label=\"debug via combined\" size=\"sm\" variant=\"secondary\" onClick={settingsCombinedWrite} />\n                        <Button label=\"Clear log\" size=\"sm\" variant=\"secondary\" layout=\"plain\" onClick={() => setLogs([])} />\n                    </div>\n                    <div\n                        className={cn('rounded-lg p-4 border', {\n                            'border-white/10 bg-black/30': isDark,\n                            'border-gray-200 bg-white': !isDark,\n                        })}\n                    >\n                        <div\n                            className={cn('text-xs uppercase tracking-wide font-semibold mb-2', {\n                                'text-gray-500': isDark,\n                                'text-gray-400': !isDark,\n                            })}\n                        >\n                            Subscriber log (slice + combined fire on every write)\n                        </div>\n                        <div\n                            className={cn('font-mono text-xs space-y-1 max-h-56 overflow-y-auto', {\n                                'text-gray-300': isDark,\n                                'text-gray-700': !isDark,\n                            })}\n                        >\n                            {logs.length === 0 && <div className=\"italic opacity-50\">Click any button above to see both layers fire</div>}\n                            {logs.map((log, i) => (\n                                <div key={i} className={cn('py-0.5 px-2 rounded', { 'bg-white/5': isDark, 'bg-gray-100': !isDark })}>\n                                    {log}\n                                </div>\n                            ))}\n                        </div>\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default BidirectionalSync;\n"
        },
        {
          "title": "StandaloneSlice",
          "code": "import cn from 'classnames';\nimport React, { useRef } from 'react';\nimport { Button } from '../../../components';\nimport { createHook, createSlice } from '../../../store';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\n\ninterface TimerState {\n    seconds: number;\n    running: boolean;\n}\n\nconst timerSlice = createSlice<TimerState>('timer', () => ({ seconds: 0, running: false }));\nconst useTimer = createHook(timerSlice);\n\nconst code = `import { createHook, createSlice } from 'fluxo-ui/store';\n\n// A slice is a fully-functional store on its own — no combineSlices needed.\nconst timerSlice = createSlice<TimerState>('timer', () => ({ seconds: 0, running: false }));\nconst useTimer = createHook(timerSlice);\n\n// Direct framework-agnostic usage from plain JavaScript:\ntimerSlice.on('change', 'seconds', (s) => console.log('seconds:', s.seconds));\ntimerSlice.setState({ running: true });\n\n// Later — adopt the same slice into a combined store with combineSlices({ timer: timerSlice, ... })\n// The slice keeps the same identity; existing subscribers keep firing.\n`;\n\nconst StandaloneSlice: React.FC = () => {\n    const { isDark } = useStoryTheme();\n    const renderCount = useRef(0);\n    renderCount.current++;\n    const state = useTimer();\n\n    const tick = () => timerSlice.setState((s) => ({ seconds: s.seconds + 1 }));\n    const toggle = () => timerSlice.setState((s) => ({ running: !s.running }));\n    const reset = () => timerSlice.reset();\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Standalone Slice\"\n                description=\"A slice used on its own — works exactly like a regular Store<T>. No combined parent required.\"\n                centered={false}\n            >\n                <div className=\"p-6 flex flex-col gap-4 items-center\">\n                    <div\n                        className={cn('rounded-lg p-6 border w-full max-w-md', {\n                            'border-white/10 bg-white/5': isDark,\n                            'border-gray-200 bg-gray-50': !isDark,\n                        })}\n                    >\n                        <div className=\"flex items-center justify-between mb-3\">\n                            <div\n                                className={cn('text-xs uppercase tracking-wide font-semibold', {\n                                    'text-gray-500': isDark,\n                                    'text-gray-400': !isDark,\n                                })}\n                            >\n                                Standalone Timer Slice\n                            </div>\n                            <div\n                                className={cn('text-xs px-2 py-0.5 rounded font-mono', {\n                                    'bg-amber-500/20 text-amber-400': isDark,\n                                    'bg-amber-100 text-amber-700': !isDark,\n                                })}\n                            >\n                                renders: {renderCount.current}\n                            </div>\n                        </div>\n                        <div className=\"text-center mb-4\">\n                            <div className=\"text-5xl font-bold tabular-nums text-[var(--eui-primary)]\">{state.seconds}</div>\n                            <div className={cn('text-sm mt-1', { 'text-gray-400': isDark, 'text-gray-500': !isDark })}>\n                                {state.running ? 'running' : 'paused'}\n                            </div>\n                        </div>\n                        <div className=\"flex justify-center gap-2 flex-wrap\">\n                            <Button label=\"Tick\" size=\"sm\" onClick={tick} />\n                            <Button label=\"Toggle\" size=\"sm\" onClick={toggle} />\n                            <Button label=\"Reset\" size=\"sm\" variant=\"secondary\" onClick={reset} />\n                        </div>\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"tsx\" />\n            </div>\n        </>\n    );\n};\n\nexport default StandaloneSlice;\n"
        },
        {
          "title": "VanillaJsExample",
          "code": "import cn from 'classnames';\nimport React, { useEffect, useRef, useState } from 'react';\nimport { Button } from '../../../components';\nimport { combineSlices, createSlice } from '../../../store';\nimport { CodeBlock } from '../../CodeBlock';\nimport { ComponentDemo } from '../../ComponentDemo';\nimport { useStoryTheme } from '../../StoryThemeContext';\n\nconst code = `// Pure TypeScript / JavaScript — no React.\nimport { combineSlices, createSlice } from 'fluxo-ui/store';\n\nconst userSlice = createSlice('user', () => ({ name: 'Guest' }));\nconst flagsSlice = createSlice('flags', () => ({ darkMode: false }));\n\nconst store = combineSlices({ user: userSlice, flags: flagsSlice });\n\n// Subscribe directly — these listeners fire in pure JS environments\n// (Node, web workers, vanilla DOM) the same way they do in React.\nstore.on('change', 'user.name', (s) => {\n    console.log('user.name =>', s.user.name);\n});\n\nuserSlice.on('change', (s) => {\n    console.log('user slice changed:', s);\n});\n\n// Writes from any side propagate everywhere.\nuserSlice.setState({ name: 'Alice' });\nstore.setState((s) => ({ flags: { ...s.flags, darkMode: true } }));\n`;\n\ninterface UserState {\n    name: string;\n}\ninterface FlagsState {\n    darkMode: boolean;\n}\n\nconst userSlice = createSlice<UserState>('user', () => ({ name: 'Guest' }));\nconst flagsSlice = createSlice<FlagsState>('flags', () => ({ darkMode: false }));\nconst vanillaStore = combineSlices({ user: userSlice, flags: flagsSlice });\n\nconst VanillaJsExample: React.FC = () => {\n    const { isDark } = useStoryTheme();\n    const [logs, setLogs] = useState<string[]>([]);\n    const counter = useRef(0);\n\n    useEffect(() => {\n        const unsub1 = vanillaStore.on('change', 'user.name', (s) => {\n            setLogs((prev) => [...prev.slice(-19), `[combined] user.name => ${s.user.name}`]);\n        });\n        const unsub2 = userSlice.on('change', (s) => {\n            setLogs((prev) => [...prev.slice(-19), `[user slice] ${JSON.stringify(s)}`]);\n        });\n        const unsub3 = flagsSlice.on('change', 'darkMode', (s) => {\n            setLogs((prev) => [...prev.slice(-19), `[flags slice] darkMode=${s.darkMode}`]);\n        });\n        return () => {\n            unsub1();\n            unsub2();\n            unsub3();\n        };\n    }, []);\n\n    const setName = () => {\n        counter.current += 1;\n        userSlice.setState({ name: `User_${counter.current}` });\n    };\n    const toggleDark = () => vanillaStore.setState((s) => ({ flags: { ...s.flags, darkMode: !s.flags.darkMode } }));\n\n    return (\n        <>\n            <ComponentDemo\n                title=\"Framework-Agnostic Core\"\n                description=\"The slicing API is plain TypeScript. It runs in Node, web workers, plain DOM apps, or any non-React framework. React is an optional thin wrapper via createHook().\"\n                centered={false}\n            >\n                <div className=\"p-6 flex flex-col gap-4\">\n                    <div\n                        className={cn('rounded-lg p-4 border flex flex-wrap gap-2', {\n                            'border-white/10 bg-white/5': isDark,\n                            'border-gray-200 bg-gray-50': !isDark,\n                        })}\n                    >\n                        <Button label=\"Set user name\" size=\"sm\" onClick={setName} />\n                        <Button label=\"Toggle darkMode (combined write)\" size=\"sm\" variant=\"secondary\" onClick={toggleDark} />\n                        <Button label=\"Clear log\" size=\"sm\" variant=\"secondary\" layout=\"plain\" onClick={() => setLogs([])} />\n                    </div>\n                    <div\n                        className={cn('rounded-lg p-4 border', {\n                            'border-white/10 bg-black/30': isDark,\n                            'border-gray-200 bg-white': !isDark,\n                        })}\n                    >\n                        <div\n                            className={cn('text-xs uppercase tracking-wide font-semibold mb-2', {\n                                'text-gray-500': isDark,\n                                'text-gray-400': !isDark,\n                            })}\n                        >\n                            Direct subscriber output (no React)\n                        </div>\n                        <div\n                            className={cn('font-mono text-xs space-y-1 max-h-56 overflow-y-auto', {\n                                'text-gray-300': isDark,\n                                'text-gray-700': !isDark,\n                            })}\n                        >\n                            {logs.length === 0 && (\n                                <div className=\"italic opacity-50\">Listeners are registered with store.on() — same API as plain JS.</div>\n                            )}\n                            {logs.map((log, i) => (\n                                <div key={i} className={cn('py-0.5 px-2 rounded', { 'bg-white/5': isDark, 'bg-gray-100': !isDark })}>\n                                    {log}\n                                </div>\n                            ))}\n                        </div>\n                    </div>\n                </div>\n            </ComponentDemo>\n            <div className=\"mt-4\">\n                <CodeBlock code={code} language=\"ts\" />\n            </div>\n        </>\n    );\n};\n\nexport default VanillaJsExample;\n"
        }
      ]
    }
  },
  "themes": {
    "available": [
      "theme-blue",
      "theme-green",
      "theme-orange",
      "theme-purple",
      "theme-lara",
      "theme-indigo",
      "theme-rose",
      "theme-amber",
      "theme-teal",
      "theme-emerald",
      "theme-fuchsia",
      "theme-slate"
    ],
    "darkModeClass": "mode-dark",
    "howToApply": "Apply a theme and dark mode by adding the class names to the <body> element. Both are optional — without them components render in the default blue/light palette.\n\ndocument.body.classList.add('theme-purple', 'mode-dark');",
    "howToImport": "Each theme ships as its own CSS subpath so only the theme you use is bundled. Import it once at your app entry:\n\nimport 'fluxo-ui/themes/purple';\n\nAvailable: fluxo-ui/themes/blue · green · orange · purple · lara · indigo · rose · amber · teal · emerald · fuchsia · slate. The default blue palette is already included with the components — only import a theme subpath if you switch to a non-blue theme.",
    "tokens": [],
    "breakpoints": [
      {
        "name": "bp-sm",
        "value": "640px"
      },
      {
        "name": "bp-md",
        "value": "768px"
      },
      {
        "name": "bp-lg",
        "value": "1024px"
      },
      {
        "name": "bp-xl",
        "value": "1280px"
      },
      {
        "name": "bp-2xl",
        "value": "1536px"
      }
    ]
  },
  "quickStart": {
    "install": "npm install fluxo-ui",
    "stylesAreAutomatic": "You do NOT need to import a global stylesheet. Importing any component automatically applies that component's CSS plus the base design tokens and dark-mode support. Just import and use:\n\nimport { Button, TextInput } from 'fluxo-ui';\n\nexport default function App() {\n  return (\n    <>\n      <TextInput placeholder=\"Your name\" />\n      <Button label=\"Submit\" />\n    </>\n  );\n}",
    "optionalTheme": "To use a brand theme other than the default blue, import its theme CSS once and add the class to <body>:\n\nimport 'fluxo-ui/themes/purple';\ndocument.body.classList.add('theme-purple');"
  },
  "managers": [
    {
      "name": "SnackbarManager",
      "purpose": "Global toast notifications",
      "api": [
        "showSnackbar",
        "hideSnackbar"
      ],
      "mountOnce": true
    },
    {
      "name": "TooltipManager",
      "purpose": "Global tooltips",
      "api": [
        "showTooltip",
        "hideTooltip"
      ],
      "mountOnce": true
    },
    {
      "name": "ContextMenuManager",
      "purpose": "Global right-click menus",
      "api": [
        "showContextMenu"
      ],
      "mountOnce": true
    }
  ]
}