@humain/ui 2.2.7 → 2.2.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index101.js +2 -2
- package/dist/index101.js.map +1 -1
- package/dist/index103.js +3 -3
- package/dist/index103.js.map +1 -1
- package/dist/index108.js +1 -1
- package/dist/index108.js.map +1 -1
- package/dist/index117.js +1 -1
- package/dist/index117.js.map +1 -1
- package/dist/index122.js +6 -6
- package/dist/index122.js.map +1 -1
- package/dist/index126.js +1 -1
- package/dist/index126.js.map +1 -1
- package/dist/index130.js +2 -2
- package/dist/index130.js.map +1 -1
- package/dist/index146.js +4 -4
- package/dist/index146.js.map +1 -1
- package/dist/index152.js +1 -1
- package/dist/index152.js.map +1 -1
- package/dist/index154.js +2 -2
- package/dist/index154.js.map +1 -1
- package/dist/index166.js +1 -1
- package/dist/index166.js.map +1 -1
- package/dist/index168.js +1 -1
- package/dist/index168.js.map +1 -1
- package/dist/index169.js +1 -1
- package/dist/index169.js.map +1 -1
- package/dist/index173.js +2 -2
- package/dist/index173.js.map +1 -1
- package/dist/index175.js +4 -4
- package/dist/index175.js.map +1 -1
- package/dist/index176.js +2 -2
- package/dist/index176.js.map +1 -1
- package/dist/index177.js +2 -2
- package/dist/index177.js.map +1 -1
- package/dist/index184.js +1 -1
- package/dist/index184.js.map +1 -1
- package/dist/index191.js +3 -3
- package/dist/index191.js.map +1 -1
- package/dist/index192.js +2 -2
- package/dist/index192.js.map +1 -1
- package/dist/index201.js +2 -2
- package/dist/index201.js.map +1 -1
- package/dist/index204.js +4 -4
- package/dist/index204.js.map +1 -1
- package/dist/index228.js +1 -1
- package/dist/index228.js.map +1 -1
- package/dist/index229.js +1 -1
- package/dist/index229.js.map +1 -1
- package/dist/index24.js +2 -2
- package/dist/index24.js.map +1 -1
- package/dist/index5.js +1 -1
- package/dist/index5.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/wc/AICodeBlock.js +41 -41
- package/dist/wc/AICodeBlock.js.map +1 -1
- package/dist/wc/AIMermaidDiagram.js +7 -7
- package/dist/wc/AIMermaidDiagram.js.map +1 -1
- package/dist/wc/AIMessage.js +6 -6
- package/dist/wc/AIMessage.js.map +1 -1
- package/dist/wc/AISource.js +2 -2
- package/dist/wc/AISource.js.map +1 -1
- package/dist/wc/AIToolCall.js +1 -1
- package/dist/wc/AIToolCall.js.map +1 -1
- package/dist/wc/Breadcrumb.js +43 -43
- package/dist/wc/Breadcrumb.js.map +1 -1
- package/dist/wc/DropdownMenu.js +9 -9
- package/dist/wc/DropdownMenu.js.map +1 -1
- package/dist/wc/Kbd.js +22 -22
- package/dist/wc/Kbd.js.map +1 -1
- package/dist/wc/button.js +7 -7
- package/dist/wc/button.js.map +1 -1
- package/dist/wc/close-button.js +19 -19
- package/dist/wc/close-button.js.map +1 -1
- package/dist/wc/hf-ai-prompt-suggestion.js +14 -14
- package/dist/wc/hf-ai-prompt-suggestion.js.map +1 -1
- package/dist/wc/hf-ai-reasoning-block.js +13 -13
- package/dist/wc/hf-ai-reasoning-block.js.map +1 -1
- package/dist/wc/hf-ai-steps.js +53 -53
- package/dist/wc/hf-ai-steps.js.map +1 -1
- package/dist/wc/hf-ai-system-message.js +26 -26
- package/dist/wc/hf-ai-system-message.js.map +1 -1
- package/dist/wc/hf-code-snippet.js +35 -35
- package/dist/wc/hf-code-snippet.js.map +1 -1
- package/dist/wc/hf-command-menu.js +39 -39
- package/dist/wc/hf-command-menu.js.map +1 -1
- package/dist/wc/hf-data-table.js +3 -3
- package/dist/wc/hf-data-table.js.map +1 -1
- package/dist/wc/hf-display-value.js +50 -50
- package/dist/wc/hf-display-value.js.map +1 -1
- package/dist/wc/hf-nav-account-menu.js +5 -5
- package/dist/wc/hf-nav-account-menu.js.map +1 -1
- package/dist/wc/hf-rich-textarea.js +1 -1
- package/dist/wc/hf-rich-textarea.js.map +1 -1
- package/dist/wc/hf-steps.js +8 -8
- package/dist/wc/hf-steps.js.map +1 -1
- package/dist/wc/markdown-renderer.js +1 -1
- package/dist/wc/markdown-renderer.js.map +1 -1
- package/dist/wc/selection-group.js +26 -26
- package/dist/wc/selection-group.js.map +1 -1
- package/dist/wc/syntax-highlight.js +4 -4
- package/dist/wc/syntax-highlight.js.map +1 -1
- package/dist/wc/workflow-step-renderer.js +51 -51
- package/dist/wc/workflow-step-renderer.js.map +1 -1
- package/dist/wc-react/AICodeBlock.js +17 -17
- package/dist/wc-react/AICodeBlock.js.map +1 -1
- package/dist/wc-react/AIMermaidDiagram.js +16 -16
- package/dist/wc-react/AIMermaidDiagram.js.map +1 -1
- package/dist/wc-react/AIMessage.js +7 -7
- package/dist/wc-react/AIMessage.js.map +1 -1
- package/dist/wc-react/AISource.js +41 -41
- package/dist/wc-react/AISource.js.map +1 -1
- package/dist/wc-react/AIToolCall.js +6 -6
- package/dist/wc-react/AIToolCall.js.map +1 -1
- package/dist/wc-react/Breadcrumb.js +18 -18
- package/dist/wc-react/Breadcrumb.js.map +1 -1
- package/dist/wc-react/DropdownMenu.js +27 -27
- package/dist/wc-react/DropdownMenu.js.map +1 -1
- package/dist/wc-react/Kbd.js +17 -17
- package/dist/wc-react/Kbd.js.map +1 -1
- package/dist/wc-react/button.js +12 -12
- package/dist/wc-react/button.js.map +1 -1
- package/dist/wc-react/close-button.js +19 -19
- package/dist/wc-react/close-button.js.map +1 -1
- package/dist/wc-react/hf-ai-prompt-suggestion.js +1 -1
- package/dist/wc-react/hf-ai-prompt-suggestion.js.map +1 -1
- package/dist/wc-react/hf-ai-reasoning-block.js +1 -1
- package/dist/wc-react/hf-ai-reasoning-block.js.map +1 -1
- package/dist/wc-react/hf-ai-steps.js +33 -33
- package/dist/wc-react/hf-ai-steps.js.map +1 -1
- package/dist/wc-react/hf-ai-system-message.js +9 -9
- package/dist/wc-react/hf-ai-system-message.js.map +1 -1
- package/dist/wc-react/hf-code-snippet.js +3 -3
- package/dist/wc-react/hf-code-snippet.js.map +1 -1
- package/dist/wc-react/hf-command-menu.js +56 -56
- package/dist/wc-react/hf-command-menu.js.map +1 -1
- package/dist/wc-react/hf-data-table.js +3 -3
- package/dist/wc-react/hf-data-table.js.map +1 -1
- package/dist/wc-react/hf-display-value.js +58 -58
- package/dist/wc-react/hf-display-value.js.map +1 -1
- package/dist/wc-react/hf-nav-account-menu.js +7 -7
- package/dist/wc-react/hf-nav-account-menu.js.map +1 -1
- package/dist/wc-react/hf-rich-textarea.js +5 -5
- package/dist/wc-react/hf-rich-textarea.js.map +1 -1
- package/dist/wc-react/hf-steps.js +2 -2
- package/dist/wc-react/hf-steps.js.map +1 -1
- package/dist/wc-react/markdown-renderer.js +1 -1
- package/dist/wc-react/markdown-renderer.js.map +1 -1
- package/dist/wc-react/selection-group.js +7 -7
- package/dist/wc-react/selection-group.js.map +1 -1
- package/dist/wc-react/syntax-highlight.js +4 -4
- package/dist/wc-react/syntax-highlight.js.map +1 -1
- package/dist/wc-react/workflow-step-renderer.js +44 -44
- package/dist/wc-react/workflow-step-renderer.js.map +1 -1
- package/package.json +1 -1
- package/skills/humain-ui/SKILL.md +1 -1
- package/skills/humain-ui-wc/SKILL.md +1 -1
- package/skills/humain-ui-wc.skill +0 -0
- package/skills/humain-ui.skill +0 -0
- package/src/tokens.css +4 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AIMermaidDiagram.js","names":[],"sources":["../../src/components/organisms/ai/AIMermaidDiagram/mermaid-theme.ts","../../src/components/organisms/ai/AIMermaidDiagram/AIMermaidDiagram.tsx","../../src/components/organisms/ai/AIMermaidDiagram/index.ts"],"sourcesContent":["import type { MermaidConfig } from 'mermaid';\n\n/**\n * Build a color palette by resolving CSS custom properties at runtime.\n * Uses a single getComputedStyle() call for efficiency, then reads\n * all token values from the cached CSSStyleDeclaration object.\n * Falls back to hard-coded hex when tokens are unavailable (SSR, missing vars).\n */\nfunction resolveColors(el?: Element | null) {\n if (typeof window === 'undefined') {\n return {\n blue500: '#3b82f6',\n blue600: '#2563eb',\n gray900: '#0f172a',\n gray50: '#f8fafc',\n gray300: '#cbd5e1',\n gray500: '#475569',\n gray200: '#e2e8f0',\n gray700: '#334155',\n gray800: '#1e293b',\n gray100: '#f1f5f9',\n };\n }\n\n const ownerDocument = el?.ownerDocument;\n const OwnerWindow = ownerDocument?.defaultView;\n\n if (!ownerDocument || !OwnerWindow) {\n return {\n blue500: '#3b82f6',\n blue600: '#2563eb',\n gray900: '#0f172a',\n gray50: '#f8fafc',\n gray300: '#cbd5e1',\n gray500: '#475569',\n gray200: '#e2e8f0',\n gray700: '#334155',\n gray800: '#1e293b',\n gray100: '#f1f5f9',\n };\n }\n\n const styles = OwnerWindow.getComputedStyle(\n el ?? ownerDocument.documentElement,\n );\n const r = (token: string, fallback: string) =>\n styles.getPropertyValue(token).trim() || fallback;\n\n return {\n blue500: r('--blue-500', '#3b82f6'),\n blue600: r('--blue-600', '#2563eb'),\n gray900: r('--gray-900', '#0f172a'),\n gray50: r('--gray-50', '#f8fafc'),\n gray300: r('--gray-300', '#cbd5e1'),\n gray500: r('--gray-500', '#475569'),\n gray200: r('--gray-200', '#e2e8f0'),\n gray700: r('--gray-700', '#334155'),\n gray800: r('--gray-800', '#1e293b'),\n gray100: r('--gray-100', '#f1f5f9'),\n };\n}\n\n/**\n * Get mermaid configuration based on theme\n *\n * Maps design system tokens to mermaid theme variables.\n * Colors are resolved from CSS custom properties at runtime so the\n * diagram follows whatever palette the host page provides. Hard-coded\n * fallbacks are used when getComputedStyle cannot read the tokens.\n */\nexport function getMermaidConfig(\n theme: 'light' | 'dark',\n el?: Element | null,\n): MermaidConfig {\n const isDark = theme === 'dark';\n const c = resolveColors(el);\n\n return {\n startOnLoad: false,\n securityLevel: 'strict',\n suppressErrorRendering: true,\n theme: 'base',\n themeVariables: {\n // Base colors\n primaryColor: isDark ? c.blue500 : c.blue600,\n primaryTextColor: isDark ? c.gray50 : c.gray900,\n primaryBorderColor: isDark ? c.gray500 : c.gray300,\n\n // Secondary colors\n secondaryColor: isDark ? c.gray700 : c.gray200,\n secondaryTextColor: isDark ? c.gray100 : c.gray800,\n secondaryBorderColor: isDark ? c.gray500 : c.gray300,\n\n // Tertiary colors\n tertiaryColor: isDark ? c.gray800 : c.gray100,\n tertiaryTextColor: isDark ? c.gray200 : c.gray700,\n tertiaryBorderColor: isDark ? c.gray700 : c.gray200,\n\n // Background\n background: isDark ? c.gray900 : '#ffffff',\n mainBkg: isDark ? c.gray800 : c.gray50,\n\n // Text\n textColor: isDark ? c.gray200 : c.gray800,\n titleColor: isDark ? c.gray50 : c.gray900,\n\n // Lines and borders\n lineColor: isDark ? c.gray500 : '#94a3b8',\n nodeBorder: isDark ? c.gray500 : c.gray300,\n\n // Notes\n noteBkgColor: isDark ? c.gray700 : '#fef9c3',\n noteTextColor: isDark ? c.gray100 : c.gray800,\n noteBorderColor: isDark ? c.gray500 : '#fde047',\n\n // Flowchart specific\n clusterBkg: isDark ? c.gray800 : c.gray100,\n clusterBorder: isDark ? c.gray700 : c.gray200,\n\n // Sequence diagram specific\n actorBkg: isDark ? c.gray800 : c.gray50,\n actorBorder: isDark ? c.gray500 : c.gray300,\n actorTextColor: isDark ? c.gray100 : c.gray800,\n actorLineColor: isDark ? '#64748b' : '#94a3b8',\n signalColor: isDark ? '#64748b' : '#64748b',\n signalTextColor: isDark ? c.gray200 : c.gray800,\n labelBoxBkgColor: isDark ? c.gray700 : c.gray100,\n labelBoxBorderColor: isDark ? c.gray500 : c.gray300,\n labelTextColor: isDark ? c.gray100 : c.gray800,\n loopTextColor: isDark ? c.gray100 : c.gray800,\n activationBkgColor: isDark ? c.blue500 : '#dbeafe',\n activationBorderColor: isDark ? c.blue600 : c.blue500,\n sequenceNumberColor: isDark ? c.gray50 : c.gray900,\n\n // Class diagram specific\n classText: isDark ? c.gray200 : c.gray800,\n\n // State diagram specific\n labelColor: isDark ? c.gray200 : c.gray800,\n\n // ER diagram specific\n entityBorder: isDark ? c.gray500 : c.gray300,\n entityBkg: isDark ? c.gray800 : c.gray50,\n entityTextColor: isDark ? c.gray100 : c.gray800,\n relationColor: isDark ? '#64748b' : '#94a3b8',\n relationLabelColor: isDark ? c.gray200 : c.gray800,\n relationLabelBackground: isDark ? c.gray900 : '#ffffff',\n attributeBackgroundColorOdd: isDark ? c.gray700 : c.gray100,\n attributeBackgroundColorEven: isDark ? c.gray800 : c.gray50,\n\n // Gantt chart specific\n sectionBkgColor: isDark ? c.gray700 : c.gray200,\n altSectionBkgColor: isDark ? c.gray800 : c.gray100,\n sectionBkgColor2: isDark ? c.gray800 : c.gray50,\n gridColor: isDark ? c.gray700 : c.gray200,\n doneTaskBkgColor: isDark ? '#22c55e' : '#86efac',\n doneTaskBorderColor: isDark ? '#16a34a' : '#22c55e',\n activeTaskBkgColor: isDark ? c.blue500 : '#93c5fd',\n activeTaskBorderColor: isDark ? c.blue600 : c.blue500,\n critBkgColor: isDark ? '#ef4444' : '#fecaca',\n critBorderColor: isDark ? '#dc2626' : '#ef4444',\n taskBkgColor: isDark ? c.gray500 : c.gray300,\n taskBorderColor: isDark ? '#64748b' : '#94a3b8',\n taskTextColor: isDark ? c.gray100 : c.gray800,\n taskTextOutsideColor: isDark ? c.gray200 : c.gray800,\n taskTextLightColor: isDark ? c.gray50 : c.gray900,\n todayLineColor: isDark ? '#f472b6' : '#ec4899',\n\n // Pie chart specific\n pieStrokeColor: isDark ? c.gray900 : '#ffffff',\n pieLegendTextColor: isDark ? c.gray200 : c.gray800,\n pieSectionTextColor: isDark ? c.gray50 : c.gray900,\n pieStrokeWidth: '2px',\n pieOuterStrokeWidth: '2px',\n pie1: isDark ? c.blue500 : c.blue600,\n pie2: isDark ? '#22c55e' : '#16a34a',\n pie3: isDark ? '#f59e0b' : '#d97706',\n pie4: isDark ? '#ef4444' : '#dc2626',\n pie5: isDark ? '#a855f7' : '#9333ea',\n pie6: isDark ? '#ec4899' : '#db2777',\n pie7: isDark ? '#06b6d4' : '#0891b2',\n pie8: isDark ? '#84cc16' : '#65a30d',\n pie9: isDark ? '#f97316' : '#ea580c',\n pie10: isDark ? '#6366f1' : '#4f46e5',\n pie11: isDark ? '#14b8a6' : '#0d9488',\n pie12: isDark ? '#f43f5e' : '#e11d48',\n\n // Mindmap specific\n mindmapColors: isDark\n ? [c.blue500, '#22c55e', '#f59e0b', '#ef4444', '#a855f7', '#ec4899']\n : [c.blue600, '#16a34a', '#d97706', '#dc2626', '#9333ea', '#db2777'],\n\n // Git diagram specific\n git0: isDark ? c.blue500 : c.blue600,\n git1: isDark ? '#22c55e' : '#16a34a',\n git2: isDark ? '#f59e0b' : '#d97706',\n git3: isDark ? '#ef4444' : '#dc2626',\n git4: isDark ? '#a855f7' : '#9333ea',\n git5: isDark ? '#ec4899' : '#db2777',\n git6: isDark ? '#06b6d4' : '#0891b2',\n git7: isDark ? '#84cc16' : '#65a30d',\n gitBranchLabel0: isDark ? c.gray50 : c.gray900,\n gitBranchLabel1: isDark ? c.gray50 : c.gray900,\n gitBranchLabel2: isDark ? c.gray50 : c.gray900,\n gitBranchLabel3: isDark ? c.gray50 : c.gray900,\n gitBranchLabel4: isDark ? c.gray50 : c.gray900,\n gitBranchLabel5: isDark ? c.gray50 : c.gray900,\n gitBranchLabel6: isDark ? c.gray50 : c.gray900,\n gitBranchLabel7: isDark ? c.gray50 : c.gray900,\n commitLabelColor: isDark ? c.gray50 : c.gray900,\n commitLabelBackground: isDark ? c.gray700 : c.gray200,\n\n // Quadrant chart specific\n quadrant1Fill: isDark ? c.blue500 : '#dbeafe',\n quadrant2Fill: isDark ? '#22c55e' : '#dcfce7',\n quadrant3Fill: isDark ? '#f59e0b' : '#fef3c7',\n quadrant4Fill: isDark ? '#ef4444' : '#fee2e2',\n quadrant1TextFill: isDark ? c.gray50 : c.gray800,\n quadrant2TextFill: isDark ? c.gray50 : c.gray800,\n quadrant3TextFill: isDark ? c.gray50 : c.gray800,\n quadrant4TextFill: isDark ? c.gray50 : c.gray800,\n quadrantPointFill: isDark ? c.gray200 : c.gray800,\n quadrantPointTextFill: isDark ? c.gray200 : c.gray800,\n quadrantExternalBorderStrokeFill: isDark ? c.gray500 : c.gray300,\n quadrantInternalBorderStrokeFill: isDark ? c.gray700 : c.gray200,\n quadrantTitleFill: isDark ? c.gray50 : c.gray900,\n quadrantXAxisTextFill: isDark ? c.gray200 : c.gray800,\n quadrantYAxisTextFill: isDark ? c.gray200 : c.gray800,\n\n // Timeline specific\n cScale0: isDark ? c.blue500 : c.blue600,\n cScale1: isDark ? '#22c55e' : '#16a34a',\n cScale2: isDark ? '#f59e0b' : '#d97706',\n cScale3: isDark ? '#ef4444' : '#dc2626',\n cScale4: isDark ? '#a855f7' : '#9333ea',\n cScale5: isDark ? '#ec4899' : '#db2777',\n cScale6: isDark ? '#06b6d4' : '#0891b2',\n cScale7: isDark ? '#84cc16' : '#65a30d',\n\n // Font settings\n fontFamily:\n 'ui-sans-serif, system-ui, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\"',\n fontSize: '14px',\n },\n flowchart: {\n htmlLabels: true,\n curve: 'basis',\n padding: 15,\n nodeSpacing: 50,\n rankSpacing: 50,\n },\n sequence: {\n diagramMarginX: 50,\n diagramMarginY: 10,\n actorMargin: 50,\n width: 150,\n height: 65,\n boxMargin: 10,\n boxTextMargin: 5,\n noteMargin: 10,\n messageMargin: 35,\n mirrorActors: true,\n bottomMarginAdj: 1,\n showSequenceNumbers: false,\n },\n gantt: {\n titleTopMargin: 25,\n barHeight: 20,\n barGap: 4,\n topPadding: 50,\n leftPadding: 75,\n gridLineStartPadding: 35,\n fontSize: 11,\n sectionFontSize: 11,\n numberSectionStyles: 4,\n },\n er: {\n diagramPadding: 20,\n layoutDirection: 'TB',\n minEntityWidth: 100,\n minEntityHeight: 75,\n entityPadding: 15,\n stroke: isDark ? c.gray500 : c.gray300,\n fill: isDark ? c.gray800 : c.gray50,\n fontSize: 12,\n },\n pie: {\n textPosition: 0.75,\n },\n mindmap: {\n padding: 10,\n maxNodeWidth: 200,\n },\n class: {\n titleTopMargin: 25,\n },\n state: {\n dividerMargin: 10,\n sizeUnit: 5,\n padding: 8,\n textHeight: 10,\n titleShift: -15,\n noteMargin: 10,\n forkWidth: 70,\n forkHeight: 7,\n miniPadding: 2,\n fontSizeFactor: 5.02,\n fontSize: 24,\n labelHeight: 16,\n edgeLengthFactor: '20',\n compositTitleSize: 35,\n radius: 5,\n },\n };\n}\n","'use client';\n\nimport * as React from 'react';\nimport { Skeleton } from '@/components/atoms/display/Skeleton';\nimport { AICodeBlock } from '@/components/organisms/ai/AICodeBlock';\nimport { cn } from '@/lib/utils';\nimport { getMermaidConfig } from './mermaid-theme';\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport interface AIMermaidDiagramProps {\n /** Mermaid diagram definition */\n code: string;\n /** Theme - follows design system */\n theme?: 'light' | 'dark' | 'auto';\n /** Optional caption below diagram */\n caption?: string;\n /** Allow pan/zoom for complex diagrams */\n interactive?: boolean;\n /** Max height before scrolling */\n maxHeight?: number;\n /** Additional class name */\n className?: string;\n}\n\nfunction getFiniteMaxHeight(maxHeight: number | undefined): number | undefined {\n return typeof maxHeight === 'number' &&\n Number.isFinite(maxHeight) &&\n maxHeight >= 0\n ? maxHeight\n : undefined;\n}\n\ntype DiagramTransform = {\n x: number;\n y: number;\n scale: number;\n};\n\ntype DiagramTransformState = {\n code: string;\n transform: DiagramTransform;\n};\n\nconst DEFAULT_TRANSFORM: DiagramTransform = { x: 0, y: 0, scale: 1 };\n\nfunction svgToDataUri(svg: string): string {\n return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}`;\n}\n\n// =============================================================================\n// Loading State\n// =============================================================================\n\nfunction DiagramSkeleton({ maxHeight }: { maxHeight?: number }) {\n return (\n <div\n className=\"flex items-center justify-center p-8 rounded-xl border border-border bg-muted\"\n style={{ minHeight: 200, maxHeight }}\n >\n <div className=\"flex flex-col items-center gap-4 w-full max-w-md\">\n <Skeleton className=\"h-4 w-3/4\" />\n <div className=\"flex items-center justify-center gap-4 w-full\">\n <Skeleton className=\"h-16 w-24 rounded-lg\" />\n <Skeleton className=\"h-1 w-8\" />\n <Skeleton className=\"h-16 w-24 rounded-lg\" />\n <Skeleton className=\"h-1 w-8\" />\n <Skeleton className=\"h-16 w-24 rounded-lg\" />\n </div>\n <Skeleton className=\"h-4 w-1/2\" />\n </div>\n </div>\n );\n}\n\n// =============================================================================\n// Error State\n// =============================================================================\n\ninterface DiagramErrorProps {\n code: string;\n error: string;\n}\n\nfunction DiagramError({ code, error }: DiagramErrorProps) {\n return (\n <div className=\"space-y-2\">\n <div\n className=\"flex items-center gap-2 px-3 py-2 rounded-lg bg-destructive/20 text-destructive text-sm\"\n role=\"alert\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n className=\"size-4 flex-shrink-0\"\n aria-hidden=\"true\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-8-5a.75.75 0 01.75.75v4.5a.75.75 0 01-1.5 0v-4.5A.75.75 0 0110 5zm0 10a1 1 0 100-2 1 1 0 000 2z\"\n clipRule=\"evenodd\"\n />\n </svg>\n <span className=\"font-medium\">Diagram parse error:</span>\n <span className=\"truncate\">{error}</span>\n </div>\n <AICodeBlock code={code} language=\"mermaid\" showLineNumbers />\n </div>\n );\n}\n\n// =============================================================================\n// Hook to detect theme\n// =============================================================================\n\nfunction getDocumentTheme(\n ownerDocument: Document | undefined,\n): 'light' | 'dark' {\n return ownerDocument?.documentElement.classList.contains('dark')\n ? 'dark'\n : 'light';\n}\n\nfunction useResolvedTheme(\n theme: 'light' | 'dark' | 'auto',\n ownerRef: React.RefObject<HTMLElement | null>,\n): 'light' | 'dark' | undefined {\n const [resolvedTheme, setResolvedTheme] = React.useState<\n 'light' | 'dark' | undefined\n >(() => (theme === 'auto' ? undefined : theme));\n\n React.useEffect(() => {\n if (theme !== 'auto') {\n setResolvedTheme(theme);\n return;\n }\n\n const ownerDocument = ownerRef.current?.ownerDocument;\n const OwnerMutationObserver = ownerDocument?.defaultView?.MutationObserver;\n if (!ownerDocument || !OwnerMutationObserver) {\n setResolvedTheme('light');\n return;\n }\n\n // Observe class changes on document element\n const observer = new OwnerMutationObserver(() => {\n setResolvedTheme(getDocumentTheme(ownerDocument));\n });\n\n observer.observe(ownerDocument.documentElement, {\n attributes: true,\n attributeFilter: ['class'],\n });\n\n // Set initial value\n setResolvedTheme(getDocumentTheme(ownerDocument));\n\n return () => observer.disconnect();\n }, [theme, ownerRef]);\n\n return resolvedTheme;\n}\n\n// =============================================================================\n// Main Component\n// =============================================================================\n\n// Counter for unique IDs\nlet diagramIdCounter = 0;\n\nfunction AIMermaidDiagram({\n code,\n theme = 'auto',\n caption,\n interactive = false,\n maxHeight,\n className,\n}: AIMermaidDiagramProps) {\n const safeMaxHeight = getFiniteMaxHeight(maxHeight);\n const [svgContent, setSvgContent] = React.useState<string | null>(null);\n const [error, setError] = React.useState<string | null>(null);\n const [isLoading, setIsLoading] = React.useState(true);\n const ownerRef = React.useRef<HTMLElement | null>(null);\n const containerRef = React.useRef<HTMLDivElement>(null);\n const resolvedTheme = useResolvedTheme(theme, ownerRef);\n const idRef = React.useRef<string>(`mermaid-diagram-${++diagramIdCounter}`);\n const setOwnerNode = React.useCallback((node: HTMLElement | null) => {\n ownerRef.current = node;\n }, []);\n\n // Pan/zoom state for interactive mode\n const [transformState, setTransformState] =\n React.useState<DiagramTransformState>(() => ({\n code,\n transform: DEFAULT_TRANSFORM,\n }));\n const [isDragging, setIsDragging] = React.useState(false);\n const dragStartRef = React.useRef({ x: 0, y: 0 });\n\n React.useEffect(() => {\n if (!resolvedTheme) {\n return;\n }\n\n const activeTheme = resolvedTheme;\n let cancelled = false;\n\n async function renderDiagram() {\n setIsLoading(true);\n setError(null);\n setSvgContent(null);\n\n try {\n // Dynamically import mermaid\n const mermaid = (await import('mermaid')).default;\n\n // Initialize with theme config\n const config = getMermaidConfig(\n activeTheme,\n ownerRef.current ?? containerRef.current,\n );\n mermaid.initialize(config);\n\n // Generate unique ID for this render\n const id = `${idRef.current}-${Date.now()}`;\n\n // Render the diagram\n // Note: mermaid.render returns sanitized SVG (securityLevel: 'strict')\n const { svg } = await mermaid.render(id, code.trim());\n\n if (!cancelled) {\n setSvgContent(svg);\n setError(null);\n }\n } catch (err) {\n if (!cancelled) {\n const errorMessage =\n err instanceof Error ? err.message : 'Failed to parse diagram';\n setError(errorMessage);\n setSvgContent(null);\n }\n } finally {\n if (!cancelled) {\n setIsLoading(false);\n }\n }\n }\n\n renderDiagram();\n\n return () => {\n cancelled = true;\n };\n }, [code, resolvedTheme]);\n\n const transform =\n transformState.code === code ? transformState.transform : DEFAULT_TRANSFORM;\n\n const setTransformForCode = React.useCallback(\n (\n nextTransform:\n | DiagramTransform\n | ((current: DiagramTransform) => DiagramTransform),\n ) => {\n setTransformState((current) => {\n const currentTransform =\n current.code === code ? current.transform : DEFAULT_TRANSFORM;\n const transform =\n typeof nextTransform === 'function'\n ? nextTransform(currentTransform)\n : nextTransform;\n return { code, transform };\n });\n },\n [code],\n );\n\n // Interactive handlers\n const handleWheel = React.useCallback(\n (e: React.WheelEvent) => {\n if (!interactive) return;\n e.preventDefault();\n\n const delta = e.deltaY > 0 ? 0.9 : 1.1;\n const newScale = Math.min(Math.max(transform.scale * delta, 0.5), 3);\n\n setTransformForCode((prev) => ({\n ...prev,\n scale: newScale,\n }));\n },\n [interactive, setTransformForCode, transform.scale],\n );\n\n const handleMouseDown = React.useCallback(\n (e: React.MouseEvent) => {\n if (!interactive) return;\n setIsDragging(true);\n dragStartRef.current = {\n x: e.clientX - transform.x,\n y: e.clientY - transform.y,\n };\n },\n [interactive, transform.x, transform.y],\n );\n\n const handleMouseMove = React.useCallback(\n (e: React.MouseEvent) => {\n if (!isDragging || !interactive) return;\n setTransformForCode((prev) => ({\n ...prev,\n x: e.clientX - dragStartRef.current.x,\n y: e.clientY - dragStartRef.current.y,\n }));\n },\n [isDragging, interactive, setTransformForCode],\n );\n\n const handleMouseUp = React.useCallback(() => {\n setIsDragging(false);\n }, []);\n\n const handleReset = React.useCallback(() => {\n setTransformForCode(DEFAULT_TRANSFORM);\n }, [setTransformForCode]);\n\n // Loading state\n if (isLoading) {\n return (\n <div ref={setOwnerNode} data-slot=\"ai-mermaid-diagram-status\">\n <DiagramSkeleton maxHeight={safeMaxHeight} />\n </div>\n );\n }\n\n // Error state\n if (error) {\n return (\n <div ref={setOwnerNode} data-slot=\"ai-mermaid-diagram-status\">\n <DiagramError code={code} error={error} />\n </div>\n );\n }\n\n // Render SVG\n if (!svgContent) {\n return (\n <div ref={setOwnerNode} data-slot=\"ai-mermaid-diagram-status\">\n <DiagramSkeleton maxHeight={safeMaxHeight} />\n </div>\n );\n }\n const svgDataUri = svgToDataUri(svgContent);\n\n return (\n <figure\n ref={setOwnerNode}\n data-slot=\"ai-mermaid-diagram\"\n className={cn('space-y-2', className)}\n >\n {/* biome-ignore lint/a11y/noStaticElementInteractions: Interactive mode requires mouse handlers for pan/zoom */}\n <div\n ref={containerRef}\n className={cn(\n 'relative overflow-hidden rounded-xl border border-border bg-muted',\n interactive && 'cursor-grab',\n isDragging && 'cursor-grabbing',\n )}\n style={{ maxHeight: safeMaxHeight }}\n onWheel={handleWheel}\n onMouseDown={handleMouseDown}\n onMouseMove={handleMouseMove}\n onMouseUp={handleMouseUp}\n onMouseLeave={handleMouseUp}\n >\n {/* SVG Container */}\n <div\n className={cn(\n 'flex items-center justify-center p-4',\n safeMaxHeight !== undefined && 'overflow-auto',\n )}\n {...(safeMaxHeight !== undefined\n ? { tabIndex: 0, role: 'region', 'aria-label': 'Diagram view' }\n : {})}\n style={\n interactive\n ? {\n transform: `translate(${transform.x}px, ${transform.y}px) scale(${transform.scale})`,\n transformOrigin: 'center center',\n transition: isDragging ? 'none' : 'transform 0.1s ease-out',\n }\n : undefined\n }\n >\n <img\n src={svgDataUri}\n alt=\"Mermaid diagram\"\n className=\"block max-w-full h-auto\"\n draggable={false}\n />\n </div>\n\n {/* Interactive controls */}\n {interactive && (\n <div className=\"absolute bottom-2 right-2 flex items-center gap-1 bg-card/80 supports-backdrop-filter:backdrop-blur-sm rounded-lg border border-border p-1\">\n <button\n type=\"button\"\n onClick={() =>\n setTransformForCode((prev) => ({\n ...prev,\n scale: Math.min(prev.scale * 1.2, 3),\n }))\n }\n className=\"p-1.5 rounded hover:bg-muted text-secondary-foreground hover:text-foreground transition-colors focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-ring\"\n aria-label=\"Zoom in\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n className=\"size-4\"\n >\n <path d=\"M10.75 4.75a.75.75 0 00-1.5 0v4.5h-4.5a.75.75 0 000 1.5h4.5v4.5a.75.75 0 001.5 0v-4.5h4.5a.75.75 0 000-1.5h-4.5v-4.5z\" />\n </svg>\n </button>\n <button\n type=\"button\"\n onClick={() =>\n setTransformForCode((prev) => ({\n ...prev,\n scale: Math.max(prev.scale * 0.8, 0.5),\n }))\n }\n className=\"p-1.5 rounded hover:bg-muted text-secondary-foreground hover:text-foreground transition-colors focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-ring\"\n aria-label=\"Zoom out\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n className=\"size-4\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M4 10a.75.75 0 01.75-.75h10.5a.75.75 0 010 1.5H4.75A.75.75 0 014 10z\"\n clipRule=\"evenodd\"\n />\n </svg>\n </button>\n <div className=\"w-px h-4 bg-border-secondary mx-0.5\" />\n <button\n type=\"button\"\n onClick={handleReset}\n className=\"p-1.5 rounded hover:bg-muted text-secondary-foreground hover:text-foreground transition-colors focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-ring\"\n aria-label=\"Reset view\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n className=\"size-4\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M15.312 11.424a5.5 5.5 0 01-9.201 2.466l-.312-.311h2.433a.75.75 0 000-1.5H3.989a.75.75 0 00-.75.75v4.242a.75.75 0 001.5 0v-2.43l.31.31a7 7 0 0011.712-3.138.75.75 0 00-1.449-.39zm1.23-3.723a.75.75 0 00.219-.53V2.929a.75.75 0 00-1.5 0v2.43l-.31-.31A7 7 0 003.239 8.188a.75.75 0 101.448.389A5.5 5.5 0 0113.89 6.11l.311.31h-2.432a.75.75 0 000 1.5h4.243a.75.75 0 00.53-.219z\"\n clipRule=\"evenodd\"\n />\n </svg>\n </button>\n <span className=\"text-xs text-text-quaternary px-1 tabular-nums\">\n {Math.round(transform.scale * 100)}%\n </span>\n </div>\n )}\n </div>\n\n {/* Caption */}\n {caption && (\n <figcaption className=\"text-sm text-muted-foreground text-center px-4\">\n {caption}\n </figcaption>\n )}\n </figure>\n );\n}\n\nAIMermaidDiagram.displayName = 'AIMermaidDiagram';\n\nexport { AIMermaidDiagram };\nexport default AIMermaidDiagram;\n","export * from './AIMermaidDiagram';\nexport { default } from './AIMermaidDiagram';\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AIMermaidDiagram.js","names":[],"sources":["../../src/components/organisms/ai/AIMermaidDiagram/mermaid-theme.ts","../../src/components/organisms/ai/AIMermaidDiagram/AIMermaidDiagram.tsx","../../src/components/organisms/ai/AIMermaidDiagram/index.ts"],"sourcesContent":["import type { MermaidConfig } from 'mermaid';\n\n/**\n * Build a color palette by resolving CSS custom properties at runtime.\n * Uses a single getComputedStyle() call for efficiency, then reads\n * all token values from the cached CSSStyleDeclaration object.\n * Falls back to hard-coded hex when tokens are unavailable (SSR, missing vars).\n */\nfunction resolveColors(el?: Element | null) {\n if (typeof window === 'undefined') {\n return {\n blue500: '#3b82f6',\n blue600: '#2563eb',\n gray900: '#0f172a',\n gray50: '#f8fafc',\n gray300: '#cbd5e1',\n gray500: '#475569',\n gray200: '#e2e8f0',\n gray700: '#334155',\n gray800: '#1e293b',\n gray100: '#f1f5f9',\n };\n }\n\n const ownerDocument = el?.ownerDocument;\n const OwnerWindow = ownerDocument?.defaultView;\n\n if (!ownerDocument || !OwnerWindow) {\n return {\n blue500: '#3b82f6',\n blue600: '#2563eb',\n gray900: '#0f172a',\n gray50: '#f8fafc',\n gray300: '#cbd5e1',\n gray500: '#475569',\n gray200: '#e2e8f0',\n gray700: '#334155',\n gray800: '#1e293b',\n gray100: '#f1f5f9',\n };\n }\n\n const styles = OwnerWindow.getComputedStyle(\n el ?? ownerDocument.documentElement,\n );\n const r = (token: string, fallback: string) =>\n styles.getPropertyValue(token).trim() || fallback;\n\n return {\n blue500: r('--blue-500', '#3b82f6'),\n blue600: r('--blue-600', '#2563eb'),\n gray900: r('--gray-900', '#0f172a'),\n gray50: r('--gray-50', '#f8fafc'),\n gray300: r('--gray-300', '#cbd5e1'),\n gray500: r('--gray-500', '#475569'),\n gray200: r('--gray-200', '#e2e8f0'),\n gray700: r('--gray-700', '#334155'),\n gray800: r('--gray-800', '#1e293b'),\n gray100: r('--gray-100', '#f1f5f9'),\n };\n}\n\n/**\n * Get mermaid configuration based on theme\n *\n * Maps design system tokens to mermaid theme variables.\n * Colors are resolved from CSS custom properties at runtime so the\n * diagram follows whatever palette the host page provides. Hard-coded\n * fallbacks are used when getComputedStyle cannot read the tokens.\n */\nexport function getMermaidConfig(\n theme: 'light' | 'dark',\n el?: Element | null,\n): MermaidConfig {\n const isDark = theme === 'dark';\n const c = resolveColors(el);\n\n return {\n startOnLoad: false,\n securityLevel: 'strict',\n suppressErrorRendering: true,\n theme: 'base',\n themeVariables: {\n // Base colors\n primaryColor: isDark ? c.blue500 : c.blue600,\n primaryTextColor: isDark ? c.gray50 : c.gray900,\n primaryBorderColor: isDark ? c.gray500 : c.gray300,\n\n // Secondary colors\n secondaryColor: isDark ? c.gray700 : c.gray200,\n secondaryTextColor: isDark ? c.gray100 : c.gray800,\n secondaryBorderColor: isDark ? c.gray500 : c.gray300,\n\n // Tertiary colors\n tertiaryColor: isDark ? c.gray800 : c.gray100,\n tertiaryTextColor: isDark ? c.gray200 : c.gray700,\n tertiaryBorderColor: isDark ? c.gray700 : c.gray200,\n\n // Background\n background: isDark ? c.gray900 : '#ffffff',\n mainBkg: isDark ? c.gray800 : c.gray50,\n\n // Text\n textColor: isDark ? c.gray200 : c.gray800,\n titleColor: isDark ? c.gray50 : c.gray900,\n\n // Lines and borders\n lineColor: isDark ? c.gray500 : '#94a3b8',\n nodeBorder: isDark ? c.gray500 : c.gray300,\n\n // Notes\n noteBkgColor: isDark ? c.gray700 : '#fef9c3',\n noteTextColor: isDark ? c.gray100 : c.gray800,\n noteBorderColor: isDark ? c.gray500 : '#fde047',\n\n // Flowchart specific\n clusterBkg: isDark ? c.gray800 : c.gray100,\n clusterBorder: isDark ? c.gray700 : c.gray200,\n\n // Sequence diagram specific\n actorBkg: isDark ? c.gray800 : c.gray50,\n actorBorder: isDark ? c.gray500 : c.gray300,\n actorTextColor: isDark ? c.gray100 : c.gray800,\n actorLineColor: isDark ? '#64748b' : '#94a3b8',\n signalColor: isDark ? '#64748b' : '#64748b',\n signalTextColor: isDark ? c.gray200 : c.gray800,\n labelBoxBkgColor: isDark ? c.gray700 : c.gray100,\n labelBoxBorderColor: isDark ? c.gray500 : c.gray300,\n labelTextColor: isDark ? c.gray100 : c.gray800,\n loopTextColor: isDark ? c.gray100 : c.gray800,\n activationBkgColor: isDark ? c.blue500 : '#dbeafe',\n activationBorderColor: isDark ? c.blue600 : c.blue500,\n sequenceNumberColor: isDark ? c.gray50 : c.gray900,\n\n // Class diagram specific\n classText: isDark ? c.gray200 : c.gray800,\n\n // State diagram specific\n labelColor: isDark ? c.gray200 : c.gray800,\n\n // ER diagram specific\n entityBorder: isDark ? c.gray500 : c.gray300,\n entityBkg: isDark ? c.gray800 : c.gray50,\n entityTextColor: isDark ? c.gray100 : c.gray800,\n relationColor: isDark ? '#64748b' : '#94a3b8',\n relationLabelColor: isDark ? c.gray200 : c.gray800,\n relationLabelBackground: isDark ? c.gray900 : '#ffffff',\n attributeBackgroundColorOdd: isDark ? c.gray700 : c.gray100,\n attributeBackgroundColorEven: isDark ? c.gray800 : c.gray50,\n\n // Gantt chart specific\n sectionBkgColor: isDark ? c.gray700 : c.gray200,\n altSectionBkgColor: isDark ? c.gray800 : c.gray100,\n sectionBkgColor2: isDark ? c.gray800 : c.gray50,\n gridColor: isDark ? c.gray700 : c.gray200,\n doneTaskBkgColor: isDark ? '#22c55e' : '#86efac',\n doneTaskBorderColor: isDark ? '#16a34a' : '#22c55e',\n activeTaskBkgColor: isDark ? c.blue500 : '#93c5fd',\n activeTaskBorderColor: isDark ? c.blue600 : c.blue500,\n critBkgColor: isDark ? '#ef4444' : '#fecaca',\n critBorderColor: isDark ? '#dc2626' : '#ef4444',\n taskBkgColor: isDark ? c.gray500 : c.gray300,\n taskBorderColor: isDark ? '#64748b' : '#94a3b8',\n taskTextColor: isDark ? c.gray100 : c.gray800,\n taskTextOutsideColor: isDark ? c.gray200 : c.gray800,\n taskTextLightColor: isDark ? c.gray50 : c.gray900,\n todayLineColor: isDark ? '#f472b6' : '#ec4899',\n\n // Pie chart specific\n pieStrokeColor: isDark ? c.gray900 : '#ffffff',\n pieLegendTextColor: isDark ? c.gray200 : c.gray800,\n pieSectionTextColor: isDark ? c.gray50 : c.gray900,\n pieStrokeWidth: '2px',\n pieOuterStrokeWidth: '2px',\n pie1: isDark ? c.blue500 : c.blue600,\n pie2: isDark ? '#22c55e' : '#16a34a',\n pie3: isDark ? '#f59e0b' : '#d97706',\n pie4: isDark ? '#ef4444' : '#dc2626',\n pie5: isDark ? '#a855f7' : '#9333ea',\n pie6: isDark ? '#ec4899' : '#db2777',\n pie7: isDark ? '#06b6d4' : '#0891b2',\n pie8: isDark ? '#84cc16' : '#65a30d',\n pie9: isDark ? '#f97316' : '#ea580c',\n pie10: isDark ? '#6366f1' : '#4f46e5',\n pie11: isDark ? '#14b8a6' : '#0d9488',\n pie12: isDark ? '#f43f5e' : '#e11d48',\n\n // Mindmap specific\n mindmapColors: isDark\n ? [c.blue500, '#22c55e', '#f59e0b', '#ef4444', '#a855f7', '#ec4899']\n : [c.blue600, '#16a34a', '#d97706', '#dc2626', '#9333ea', '#db2777'],\n\n // Git diagram specific\n git0: isDark ? c.blue500 : c.blue600,\n git1: isDark ? '#22c55e' : '#16a34a',\n git2: isDark ? '#f59e0b' : '#d97706',\n git3: isDark ? '#ef4444' : '#dc2626',\n git4: isDark ? '#a855f7' : '#9333ea',\n git5: isDark ? '#ec4899' : '#db2777',\n git6: isDark ? '#06b6d4' : '#0891b2',\n git7: isDark ? '#84cc16' : '#65a30d',\n gitBranchLabel0: isDark ? c.gray50 : c.gray900,\n gitBranchLabel1: isDark ? c.gray50 : c.gray900,\n gitBranchLabel2: isDark ? c.gray50 : c.gray900,\n gitBranchLabel3: isDark ? c.gray50 : c.gray900,\n gitBranchLabel4: isDark ? c.gray50 : c.gray900,\n gitBranchLabel5: isDark ? c.gray50 : c.gray900,\n gitBranchLabel6: isDark ? c.gray50 : c.gray900,\n gitBranchLabel7: isDark ? c.gray50 : c.gray900,\n commitLabelColor: isDark ? c.gray50 : c.gray900,\n commitLabelBackground: isDark ? c.gray700 : c.gray200,\n\n // Quadrant chart specific\n quadrant1Fill: isDark ? c.blue500 : '#dbeafe',\n quadrant2Fill: isDark ? '#22c55e' : '#dcfce7',\n quadrant3Fill: isDark ? '#f59e0b' : '#fef3c7',\n quadrant4Fill: isDark ? '#ef4444' : '#fee2e2',\n quadrant1TextFill: isDark ? c.gray50 : c.gray800,\n quadrant2TextFill: isDark ? c.gray50 : c.gray800,\n quadrant3TextFill: isDark ? c.gray50 : c.gray800,\n quadrant4TextFill: isDark ? c.gray50 : c.gray800,\n quadrantPointFill: isDark ? c.gray200 : c.gray800,\n quadrantPointTextFill: isDark ? c.gray200 : c.gray800,\n quadrantExternalBorderStrokeFill: isDark ? c.gray500 : c.gray300,\n quadrantInternalBorderStrokeFill: isDark ? c.gray700 : c.gray200,\n quadrantTitleFill: isDark ? c.gray50 : c.gray900,\n quadrantXAxisTextFill: isDark ? c.gray200 : c.gray800,\n quadrantYAxisTextFill: isDark ? c.gray200 : c.gray800,\n\n // Timeline specific\n cScale0: isDark ? c.blue500 : c.blue600,\n cScale1: isDark ? '#22c55e' : '#16a34a',\n cScale2: isDark ? '#f59e0b' : '#d97706',\n cScale3: isDark ? '#ef4444' : '#dc2626',\n cScale4: isDark ? '#a855f7' : '#9333ea',\n cScale5: isDark ? '#ec4899' : '#db2777',\n cScale6: isDark ? '#06b6d4' : '#0891b2',\n cScale7: isDark ? '#84cc16' : '#65a30d',\n\n // Font settings\n fontFamily:\n 'ui-sans-serif, system-ui, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\"',\n fontSize: '14px',\n },\n flowchart: {\n htmlLabels: true,\n curve: 'basis',\n padding: 15,\n nodeSpacing: 50,\n rankSpacing: 50,\n },\n sequence: {\n diagramMarginX: 50,\n diagramMarginY: 10,\n actorMargin: 50,\n width: 150,\n height: 65,\n boxMargin: 10,\n boxTextMargin: 5,\n noteMargin: 10,\n messageMargin: 35,\n mirrorActors: true,\n bottomMarginAdj: 1,\n showSequenceNumbers: false,\n },\n gantt: {\n titleTopMargin: 25,\n barHeight: 20,\n barGap: 4,\n topPadding: 50,\n leftPadding: 75,\n gridLineStartPadding: 35,\n fontSize: 11,\n sectionFontSize: 11,\n numberSectionStyles: 4,\n },\n er: {\n diagramPadding: 20,\n layoutDirection: 'TB',\n minEntityWidth: 100,\n minEntityHeight: 75,\n entityPadding: 15,\n stroke: isDark ? c.gray500 : c.gray300,\n fill: isDark ? c.gray800 : c.gray50,\n fontSize: 12,\n },\n pie: {\n textPosition: 0.75,\n },\n mindmap: {\n padding: 10,\n maxNodeWidth: 200,\n },\n class: {\n titleTopMargin: 25,\n },\n state: {\n dividerMargin: 10,\n sizeUnit: 5,\n padding: 8,\n textHeight: 10,\n titleShift: -15,\n noteMargin: 10,\n forkWidth: 70,\n forkHeight: 7,\n miniPadding: 2,\n fontSizeFactor: 5.02,\n fontSize: 24,\n labelHeight: 16,\n edgeLengthFactor: '20',\n compositTitleSize: 35,\n radius: 5,\n },\n };\n}\n","'use client';\n\nimport * as React from 'react';\nimport { Skeleton } from '@/components/atoms/display/Skeleton';\nimport { AICodeBlock } from '@/components/organisms/ai/AICodeBlock';\nimport { cn } from '@/lib/utils';\nimport { getMermaidConfig } from './mermaid-theme';\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport interface AIMermaidDiagramProps {\n /** Mermaid diagram definition */\n code: string;\n /** Theme - follows design system */\n theme?: 'light' | 'dark' | 'auto';\n /** Optional caption below diagram */\n caption?: string;\n /** Allow pan/zoom for complex diagrams */\n interactive?: boolean;\n /** Max height before scrolling */\n maxHeight?: number;\n /** Additional class name */\n className?: string;\n}\n\nfunction getFiniteMaxHeight(maxHeight: number | undefined): number | undefined {\n return typeof maxHeight === 'number' &&\n Number.isFinite(maxHeight) &&\n maxHeight >= 0\n ? maxHeight\n : undefined;\n}\n\ntype DiagramTransform = {\n x: number;\n y: number;\n scale: number;\n};\n\ntype DiagramTransformState = {\n code: string;\n transform: DiagramTransform;\n};\n\nconst DEFAULT_TRANSFORM: DiagramTransform = { x: 0, y: 0, scale: 1 };\n\nfunction svgToDataUri(svg: string): string {\n return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}`;\n}\n\n// =============================================================================\n// Loading State\n// =============================================================================\n\nfunction DiagramSkeleton({ maxHeight }: { maxHeight?: number }) {\n return (\n <div\n className=\"flex items-center justify-center p-8 rounded-xl border border-border bg-muted\"\n style={{ minHeight: 200, maxHeight }}\n >\n <div className=\"flex flex-col items-center gap-4 w-full max-w-md\">\n <Skeleton className=\"h-4 w-3/4\" />\n <div className=\"flex items-center justify-center gap-4 w-full\">\n <Skeleton className=\"h-16 w-24 rounded-lg\" />\n <Skeleton className=\"h-1 w-8\" />\n <Skeleton className=\"h-16 w-24 rounded-lg\" />\n <Skeleton className=\"h-1 w-8\" />\n <Skeleton className=\"h-16 w-24 rounded-lg\" />\n </div>\n <Skeleton className=\"h-4 w-1/2\" />\n </div>\n </div>\n );\n}\n\n// =============================================================================\n// Error State\n// =============================================================================\n\ninterface DiagramErrorProps {\n code: string;\n error: string;\n}\n\nfunction DiagramError({ code, error }: DiagramErrorProps) {\n return (\n <div className=\"space-y-2\">\n <div\n className=\"flex items-center gap-2 px-3 py-2 rounded-lg bg-destructive/20 text-destructive text-sm\"\n role=\"alert\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n className=\"size-4 flex-shrink-0\"\n aria-hidden=\"true\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-8-5a.75.75 0 01.75.75v4.5a.75.75 0 01-1.5 0v-4.5A.75.75 0 0110 5zm0 10a1 1 0 100-2 1 1 0 000 2z\"\n clipRule=\"evenodd\"\n />\n </svg>\n <span className=\"font-medium\">Diagram parse error:</span>\n <span className=\"truncate\">{error}</span>\n </div>\n <AICodeBlock code={code} language=\"mermaid\" showLineNumbers />\n </div>\n );\n}\n\n// =============================================================================\n// Hook to detect theme\n// =============================================================================\n\nfunction getDocumentTheme(\n ownerDocument: Document | undefined,\n): 'light' | 'dark' {\n return ownerDocument?.documentElement.classList.contains('dark')\n ? 'dark'\n : 'light';\n}\n\nfunction useResolvedTheme(\n theme: 'light' | 'dark' | 'auto',\n ownerRef: React.RefObject<HTMLElement | null>,\n): 'light' | 'dark' | undefined {\n const [resolvedTheme, setResolvedTheme] = React.useState<\n 'light' | 'dark' | undefined\n >(() => (theme === 'auto' ? undefined : theme));\n\n React.useEffect(() => {\n if (theme !== 'auto') {\n setResolvedTheme(theme);\n return;\n }\n\n const ownerDocument = ownerRef.current?.ownerDocument;\n const OwnerMutationObserver = ownerDocument?.defaultView?.MutationObserver;\n if (!ownerDocument || !OwnerMutationObserver) {\n setResolvedTheme('light');\n return;\n }\n\n // Observe class changes on document element\n const observer = new OwnerMutationObserver(() => {\n setResolvedTheme(getDocumentTheme(ownerDocument));\n });\n\n observer.observe(ownerDocument.documentElement, {\n attributes: true,\n attributeFilter: ['class'],\n });\n\n // Set initial value\n setResolvedTheme(getDocumentTheme(ownerDocument));\n\n return () => observer.disconnect();\n }, [theme, ownerRef]);\n\n return resolvedTheme;\n}\n\n// =============================================================================\n// Main Component\n// =============================================================================\n\n// Counter for unique IDs\nlet diagramIdCounter = 0;\n\nfunction AIMermaidDiagram({\n code,\n theme = 'auto',\n caption,\n interactive = false,\n maxHeight,\n className,\n}: AIMermaidDiagramProps) {\n const safeMaxHeight = getFiniteMaxHeight(maxHeight);\n const [svgContent, setSvgContent] = React.useState<string | null>(null);\n const [error, setError] = React.useState<string | null>(null);\n const [isLoading, setIsLoading] = React.useState(true);\n const ownerRef = React.useRef<HTMLElement | null>(null);\n const containerRef = React.useRef<HTMLDivElement>(null);\n const resolvedTheme = useResolvedTheme(theme, ownerRef);\n const idRef = React.useRef<string>(`mermaid-diagram-${++diagramIdCounter}`);\n const setOwnerNode = React.useCallback((node: HTMLElement | null) => {\n ownerRef.current = node;\n }, []);\n\n // Pan/zoom state for interactive mode\n const [transformState, setTransformState] =\n React.useState<DiagramTransformState>(() => ({\n code,\n transform: DEFAULT_TRANSFORM,\n }));\n const [isDragging, setIsDragging] = React.useState(false);\n const dragStartRef = React.useRef({ x: 0, y: 0 });\n\n React.useEffect(() => {\n if (!resolvedTheme) {\n return;\n }\n\n const activeTheme = resolvedTheme;\n let cancelled = false;\n\n async function renderDiagram() {\n setIsLoading(true);\n setError(null);\n setSvgContent(null);\n\n try {\n // Dynamically import mermaid\n const mermaid = (await import('mermaid')).default;\n\n // Initialize with theme config\n const config = getMermaidConfig(\n activeTheme,\n ownerRef.current ?? containerRef.current,\n );\n mermaid.initialize(config);\n\n // Generate unique ID for this render\n const id = `${idRef.current}-${Date.now()}`;\n\n // Render the diagram\n // Note: mermaid.render returns sanitized SVG (securityLevel: 'strict')\n const { svg } = await mermaid.render(id, code.trim());\n\n if (!cancelled) {\n setSvgContent(svg);\n setError(null);\n }\n } catch (err) {\n if (!cancelled) {\n const errorMessage =\n err instanceof Error ? err.message : 'Failed to parse diagram';\n setError(errorMessage);\n setSvgContent(null);\n }\n } finally {\n if (!cancelled) {\n setIsLoading(false);\n }\n }\n }\n\n renderDiagram();\n\n return () => {\n cancelled = true;\n };\n }, [code, resolvedTheme]);\n\n const transform =\n transformState.code === code ? transformState.transform : DEFAULT_TRANSFORM;\n\n const setTransformForCode = React.useCallback(\n (\n nextTransform:\n | DiagramTransform\n | ((current: DiagramTransform) => DiagramTransform),\n ) => {\n setTransformState((current) => {\n const currentTransform =\n current.code === code ? current.transform : DEFAULT_TRANSFORM;\n const transform =\n typeof nextTransform === 'function'\n ? nextTransform(currentTransform)\n : nextTransform;\n return { code, transform };\n });\n },\n [code],\n );\n\n // Interactive handlers\n const handleWheel = React.useCallback(\n (e: React.WheelEvent) => {\n if (!interactive) return;\n e.preventDefault();\n\n const delta = e.deltaY > 0 ? 0.9 : 1.1;\n const newScale = Math.min(Math.max(transform.scale * delta, 0.5), 3);\n\n setTransformForCode((prev) => ({\n ...prev,\n scale: newScale,\n }));\n },\n [interactive, setTransformForCode, transform.scale],\n );\n\n const handleMouseDown = React.useCallback(\n (e: React.MouseEvent) => {\n if (!interactive) return;\n setIsDragging(true);\n dragStartRef.current = {\n x: e.clientX - transform.x,\n y: e.clientY - transform.y,\n };\n },\n [interactive, transform.x, transform.y],\n );\n\n const handleMouseMove = React.useCallback(\n (e: React.MouseEvent) => {\n if (!isDragging || !interactive) return;\n setTransformForCode((prev) => ({\n ...prev,\n x: e.clientX - dragStartRef.current.x,\n y: e.clientY - dragStartRef.current.y,\n }));\n },\n [isDragging, interactive, setTransformForCode],\n );\n\n const handleMouseUp = React.useCallback(() => {\n setIsDragging(false);\n }, []);\n\n const handleReset = React.useCallback(() => {\n setTransformForCode(DEFAULT_TRANSFORM);\n }, [setTransformForCode]);\n\n // Loading state\n if (isLoading) {\n return (\n <div ref={setOwnerNode} data-slot=\"ai-mermaid-diagram-status\">\n <DiagramSkeleton maxHeight={safeMaxHeight} />\n </div>\n );\n }\n\n // Error state\n if (error) {\n return (\n <div ref={setOwnerNode} data-slot=\"ai-mermaid-diagram-status\">\n <DiagramError code={code} error={error} />\n </div>\n );\n }\n\n // Render SVG\n if (!svgContent) {\n return (\n <div ref={setOwnerNode} data-slot=\"ai-mermaid-diagram-status\">\n <DiagramSkeleton maxHeight={safeMaxHeight} />\n </div>\n );\n }\n const svgDataUri = svgToDataUri(svgContent);\n\n return (\n <figure\n ref={setOwnerNode}\n data-slot=\"ai-mermaid-diagram\"\n className={cn('space-y-2', className)}\n >\n {/* biome-ignore lint/a11y/noStaticElementInteractions: Interactive mode requires mouse handlers for pan/zoom */}\n <div\n ref={containerRef}\n className={cn(\n 'relative overflow-hidden rounded-xl border border-border bg-muted',\n interactive && 'cursor-grab',\n isDragging && 'cursor-grabbing',\n )}\n style={{ maxHeight: safeMaxHeight }}\n onWheel={handleWheel}\n onMouseDown={handleMouseDown}\n onMouseMove={handleMouseMove}\n onMouseUp={handleMouseUp}\n onMouseLeave={handleMouseUp}\n >\n {/* SVG Container */}\n <div\n className={cn(\n 'flex items-center justify-center p-4',\n safeMaxHeight !== undefined && 'overflow-auto',\n )}\n {...(safeMaxHeight !== undefined\n ? { tabIndex: 0, role: 'region', 'aria-label': 'Diagram view' }\n : {})}\n style={\n interactive\n ? {\n transform: `translate(${transform.x}px, ${transform.y}px) scale(${transform.scale})`,\n transformOrigin: 'center center',\n transition: isDragging ? 'none' : 'transform 0.1s ease-out',\n }\n : undefined\n }\n >\n <img\n src={svgDataUri}\n alt=\"Mermaid diagram\"\n className=\"block max-w-full h-auto\"\n draggable={false}\n />\n </div>\n\n {/* Interactive controls */}\n {interactive && (\n <div className=\"absolute bottom-2 right-2 flex items-center gap-1 bg-card/80 supports-backdrop-filter:backdrop-blur-sm rounded-lg border border-border p-1\">\n <button\n type=\"button\"\n onClick={() =>\n setTransformForCode((prev) => ({\n ...prev,\n scale: Math.min(prev.scale * 1.2, 3),\n }))\n }\n className=\"p-1.5 rounded hover:bg-muted text-secondary-foreground hover:text-foreground transition-colors focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-ring\"\n aria-label=\"Zoom in\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n className=\"size-4\"\n >\n <path d=\"M10.75 4.75a.75.75 0 00-1.5 0v4.5h-4.5a.75.75 0 000 1.5h4.5v4.5a.75.75 0 001.5 0v-4.5h4.5a.75.75 0 000-1.5h-4.5v-4.5z\" />\n </svg>\n </button>\n <button\n type=\"button\"\n onClick={() =>\n setTransformForCode((prev) => ({\n ...prev,\n scale: Math.max(prev.scale * 0.8, 0.5),\n }))\n }\n className=\"p-1.5 rounded hover:bg-muted text-secondary-foreground hover:text-foreground transition-colors focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-ring\"\n aria-label=\"Zoom out\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n className=\"size-4\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M4 10a.75.75 0 01.75-.75h10.5a.75.75 0 010 1.5H4.75A.75.75 0 014 10z\"\n clipRule=\"evenodd\"\n />\n </svg>\n </button>\n <div className=\"w-px h-4 bg-border-secondary mx-0.5\" />\n <button\n type=\"button\"\n onClick={handleReset}\n className=\"p-1.5 rounded hover:bg-muted text-secondary-foreground hover:text-foreground transition-colors focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-ring\"\n aria-label=\"Reset view\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n className=\"size-4\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M15.312 11.424a5.5 5.5 0 01-9.201 2.466l-.312-.311h2.433a.75.75 0 000-1.5H3.989a.75.75 0 00-.75.75v4.242a.75.75 0 001.5 0v-2.43l.31.31a7 7 0 0011.712-3.138.75.75 0 00-1.449-.39zm1.23-3.723a.75.75 0 00.219-.53V2.929a.75.75 0 00-1.5 0v2.43l-.31-.31A7 7 0 003.239 8.188a.75.75 0 101.448.389A5.5 5.5 0 0113.89 6.11l.311.31h-2.432a.75.75 0 000 1.5h4.243a.75.75 0 00.53-.219z\"\n clipRule=\"evenodd\"\n />\n </svg>\n </button>\n <span className=\"text-xs text-secondary-foreground px-1 tabular-nums\">\n {Math.round(transform.scale * 100)}%\n </span>\n </div>\n )}\n </div>\n\n {/* Caption */}\n {caption && (\n <figcaption className=\"text-sm text-muted-foreground text-center px-4\">\n {caption}\n </figcaption>\n )}\n </figure>\n );\n}\n\nAIMermaidDiagram.displayName = 'AIMermaidDiagram';\n\nexport { AIMermaidDiagram };\nexport default AIMermaidDiagram;\n","export * from './AIMermaidDiagram';\nexport { default } from './AIMermaidDiagram';\n"],"mappings":";;;;;;AAQA,SAAS,EAAc,GAAqB;AAC1C,MAAI,OAAO,SAAW,IACpB,QAAO;AAAA,IACL,SAAS;AAAA,IACT,SAAS;AAAA,IACT,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,SAAS;AAAA,IACT,SAAS;AAAA,IACT,SAAS;AAAA,IACT,SAAS;AAAA,IACT,SAAS;AAAA,EACX;AAGF,QAAM,IAAgB,GAAI,eACpB,IAAc,GAAe;AAEnC,MAAI,CAAC,KAAiB,CAAC,EACrB,QAAO;AAAA,IACL,SAAS;AAAA,IACT,SAAS;AAAA,IACT,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,SAAS;AAAA,IACT,SAAS;AAAA,IACT,SAAS;AAAA,IACT,SAAS;AAAA,IACT,SAAS;AAAA,EACX;AAGF,QAAM,IAAS,EAAY,iBACzB,KAAM,EAAc,eACtB,GACM,IAAA,CAAK,GAAe,MACxB,EAAO,iBAAiB,CAAK,EAAE,KAAK,KAAK;AAE3C,SAAO;AAAA,IACL,SAAS,EAAE,cAAc,SAAS;AAAA,IAClC,SAAS,EAAE,cAAc,SAAS;AAAA,IAClC,SAAS,EAAE,cAAc,SAAS;AAAA,IAClC,QAAQ,EAAE,aAAa,SAAS;AAAA,IAChC,SAAS,EAAE,cAAc,SAAS;AAAA,IAClC,SAAS,EAAE,cAAc,SAAS;AAAA,IAClC,SAAS,EAAE,cAAc,SAAS;AAAA,IAClC,SAAS,EAAE,cAAc,SAAS;AAAA,IAClC,SAAS,EAAE,cAAc,SAAS;AAAA,IAClC,SAAS,EAAE,cAAc,SAAS;AAAA,EACpC;AACF;AAUA,SAAgB,EACd,GACA,GACe;AACf,QAAM,IAAS,MAAU,QACnB,IAAI,EAAc,CAAE;AAE1B,SAAO;AAAA,IACL,aAAa;AAAA,IACb,eAAe;AAAA,IACf,wBAAwB;AAAA,IACxB,OAAO;AAAA,IACP,gBAAgB;AAAA,MAEd,cAAc,IAAS,EAAE,UAAU,EAAE;AAAA,MACrC,kBAAkB,IAAS,EAAE,SAAS,EAAE;AAAA,MACxC,oBAAoB,IAAS,EAAE,UAAU,EAAE;AAAA,MAG3C,gBAAgB,IAAS,EAAE,UAAU,EAAE;AAAA,MACvC,oBAAoB,IAAS,EAAE,UAAU,EAAE;AAAA,MAC3C,sBAAsB,IAAS,EAAE,UAAU,EAAE;AAAA,MAG7C,eAAe,IAAS,EAAE,UAAU,EAAE;AAAA,MACtC,mBAAmB,IAAS,EAAE,UAAU,EAAE;AAAA,MAC1C,qBAAqB,IAAS,EAAE,UAAU,EAAE;AAAA,MAG5C,YAAY,IAAS,EAAE,UAAU;AAAA,MACjC,SAAS,IAAS,EAAE,UAAU,EAAE;AAAA,MAGhC,WAAW,IAAS,EAAE,UAAU,EAAE;AAAA,MAClC,YAAY,IAAS,EAAE,SAAS,EAAE;AAAA,MAGlC,WAAW,IAAS,EAAE,UAAU;AAAA,MAChC,YAAY,IAAS,EAAE,UAAU,EAAE;AAAA,MAGnC,cAAc,IAAS,EAAE,UAAU;AAAA,MACnC,eAAe,IAAS,EAAE,UAAU,EAAE;AAAA,MACtC,iBAAiB,IAAS,EAAE,UAAU;AAAA,MAGtC,YAAY,IAAS,EAAE,UAAU,EAAE;AAAA,MACnC,eAAe,IAAS,EAAE,UAAU,EAAE;AAAA,MAGtC,UAAU,IAAS,EAAE,UAAU,EAAE;AAAA,MACjC,aAAa,IAAS,EAAE,UAAU,EAAE;AAAA,MACpC,gBAAgB,IAAS,EAAE,UAAU,EAAE;AAAA,MACvC,gBAAgB,IAAS,YAAY;AAAA,MACrC,aAAsB;AAAA,MACtB,iBAAiB,IAAS,EAAE,UAAU,EAAE;AAAA,MACxC,kBAAkB,IAAS,EAAE,UAAU,EAAE;AAAA,MACzC,qBAAqB,IAAS,EAAE,UAAU,EAAE;AAAA,MAC5C,gBAAgB,IAAS,EAAE,UAAU,EAAE;AAAA,MACvC,eAAe,IAAS,EAAE,UAAU,EAAE;AAAA,MACtC,oBAAoB,IAAS,EAAE,UAAU;AAAA,MACzC,uBAAuB,IAAS,EAAE,UAAU,EAAE;AAAA,MAC9C,qBAAqB,IAAS,EAAE,SAAS,EAAE;AAAA,MAG3C,WAAW,IAAS,EAAE,UAAU,EAAE;AAAA,MAGlC,YAAY,IAAS,EAAE,UAAU,EAAE;AAAA,MAGnC,cAAc,IAAS,EAAE,UAAU,EAAE;AAAA,MACrC,WAAW,IAAS,EAAE,UAAU,EAAE;AAAA,MAClC,iBAAiB,IAAS,EAAE,UAAU,EAAE;AAAA,MACxC,eAAe,IAAS,YAAY;AAAA,MACpC,oBAAoB,IAAS,EAAE,UAAU,EAAE;AAAA,MAC3C,yBAAyB,IAAS,EAAE,UAAU;AAAA,MAC9C,6BAA6B,IAAS,EAAE,UAAU,EAAE;AAAA,MACpD,8BAA8B,IAAS,EAAE,UAAU,EAAE;AAAA,MAGrD,iBAAiB,IAAS,EAAE,UAAU,EAAE;AAAA,MACxC,oBAAoB,IAAS,EAAE,UAAU,EAAE;AAAA,MAC3C,kBAAkB,IAAS,EAAE,UAAU,EAAE;AAAA,MACzC,WAAW,IAAS,EAAE,UAAU,EAAE;AAAA,MAClC,kBAAkB,IAAS,YAAY;AAAA,MACvC,qBAAqB,IAAS,YAAY;AAAA,MAC1C,oBAAoB,IAAS,EAAE,UAAU;AAAA,MACzC,uBAAuB,IAAS,EAAE,UAAU,EAAE;AAAA,MAC9C,cAAc,IAAS,YAAY;AAAA,MACnC,iBAAiB,IAAS,YAAY;AAAA,MACtC,cAAc,IAAS,EAAE,UAAU,EAAE;AAAA,MACrC,iBAAiB,IAAS,YAAY;AAAA,MACtC,eAAe,IAAS,EAAE,UAAU,EAAE;AAAA,MACtC,sBAAsB,IAAS,EAAE,UAAU,EAAE;AAAA,MAC7C,oBAAoB,IAAS,EAAE,SAAS,EAAE;AAAA,MAC1C,gBAAgB,IAAS,YAAY;AAAA,MAGrC,gBAAgB,IAAS,EAAE,UAAU;AAAA,MACrC,oBAAoB,IAAS,EAAE,UAAU,EAAE;AAAA,MAC3C,qBAAqB,IAAS,EAAE,SAAS,EAAE;AAAA,MAC3C,gBAAgB;AAAA,MAChB,qBAAqB;AAAA,MACrB,MAAM,IAAS,EAAE,UAAU,EAAE;AAAA,MAC7B,MAAM,IAAS,YAAY;AAAA,MAC3B,MAAM,IAAS,YAAY;AAAA,MAC3B,MAAM,IAAS,YAAY;AAAA,MAC3B,MAAM,IAAS,YAAY;AAAA,MAC3B,MAAM,IAAS,YAAY;AAAA,MAC3B,MAAM,IAAS,YAAY;AAAA,MAC3B,MAAM,IAAS,YAAY;AAAA,MAC3B,MAAM,IAAS,YAAY;AAAA,MAC3B,OAAO,IAAS,YAAY;AAAA,MAC5B,OAAO,IAAS,YAAY;AAAA,MAC5B,OAAO,IAAS,YAAY;AAAA,MAG5B,eAAe,IACX;AAAA,QAAC,EAAE;AAAA,QAAS;AAAA,QAAW;AAAA,QAAW;AAAA,QAAW;AAAA,QAAW;AAAA,MAAS,IACjE;AAAA,QAAC,EAAE;AAAA,QAAS;AAAA,QAAW;AAAA,QAAW;AAAA,QAAW;AAAA,QAAW;AAAA,MAAS;AAAA,MAGrE,MAAM,IAAS,EAAE,UAAU,EAAE;AAAA,MAC7B,MAAM,IAAS,YAAY;AAAA,MAC3B,MAAM,IAAS,YAAY;AAAA,MAC3B,MAAM,IAAS,YAAY;AAAA,MAC3B,MAAM,IAAS,YAAY;AAAA,MAC3B,MAAM,IAAS,YAAY;AAAA,MAC3B,MAAM,IAAS,YAAY;AAAA,MAC3B,MAAM,IAAS,YAAY;AAAA,MAC3B,iBAAiB,IAAS,EAAE,SAAS,EAAE;AAAA,MACvC,iBAAiB,IAAS,EAAE,SAAS,EAAE;AAAA,MACvC,iBAAiB,IAAS,EAAE,SAAS,EAAE;AAAA,MACvC,iBAAiB,IAAS,EAAE,SAAS,EAAE;AAAA,MACvC,iBAAiB,IAAS,EAAE,SAAS,EAAE;AAAA,MACvC,iBAAiB,IAAS,EAAE,SAAS,EAAE;AAAA,MACvC,iBAAiB,IAAS,EAAE,SAAS,EAAE;AAAA,MACvC,iBAAiB,IAAS,EAAE,SAAS,EAAE;AAAA,MACvC,kBAAkB,IAAS,EAAE,SAAS,EAAE;AAAA,MACxC,uBAAuB,IAAS,EAAE,UAAU,EAAE;AAAA,MAG9C,eAAe,IAAS,EAAE,UAAU;AAAA,MACpC,eAAe,IAAS,YAAY;AAAA,MACpC,eAAe,IAAS,YAAY;AAAA,MACpC,eAAe,IAAS,YAAY;AAAA,MACpC,mBAAmB,IAAS,EAAE,SAAS,EAAE;AAAA,MACzC,mBAAmB,IAAS,EAAE,SAAS,EAAE;AAAA,MACzC,mBAAmB,IAAS,EAAE,SAAS,EAAE;AAAA,MACzC,mBAAmB,IAAS,EAAE,SAAS,EAAE;AAAA,MACzC,mBAAmB,IAAS,EAAE,UAAU,EAAE;AAAA,MAC1C,uBAAuB,IAAS,EAAE,UAAU,EAAE;AAAA,MAC9C,kCAAkC,IAAS,EAAE,UAAU,EAAE;AAAA,MACzD,kCAAkC,IAAS,EAAE,UAAU,EAAE;AAAA,MACzD,mBAAmB,IAAS,EAAE,SAAS,EAAE;AAAA,MACzC,uBAAuB,IAAS,EAAE,UAAU,EAAE;AAAA,MAC9C,uBAAuB,IAAS,EAAE,UAAU,EAAE;AAAA,MAG9C,SAAS,IAAS,EAAE,UAAU,EAAE;AAAA,MAChC,SAAS,IAAS,YAAY;AAAA,MAC9B,SAAS,IAAS,YAAY;AAAA,MAC9B,SAAS,IAAS,YAAY;AAAA,MAC9B,SAAS,IAAS,YAAY;AAAA,MAC9B,SAAS,IAAS,YAAY;AAAA,MAC9B,SAAS,IAAS,YAAY;AAAA,MAC9B,SAAS,IAAS,YAAY;AAAA,MAG9B,YACE;AAAA,MACF,UAAU;AAAA,IACZ;AAAA,IACA,WAAW;AAAA,MACT,YAAY;AAAA,MACZ,OAAO;AAAA,MACP,SAAS;AAAA,MACT,aAAa;AAAA,MACb,aAAa;AAAA,IACf;AAAA,IACA,UAAU;AAAA,MACR,gBAAgB;AAAA,MAChB,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,WAAW;AAAA,MACX,eAAe;AAAA,MACf,YAAY;AAAA,MACZ,eAAe;AAAA,MACf,cAAc;AAAA,MACd,iBAAiB;AAAA,MACjB,qBAAqB;AAAA,IACvB;AAAA,IACA,OAAO;AAAA,MACL,gBAAgB;AAAA,MAChB,WAAW;AAAA,MACX,QAAQ;AAAA,MACR,YAAY;AAAA,MACZ,aAAa;AAAA,MACb,sBAAsB;AAAA,MACtB,UAAU;AAAA,MACV,iBAAiB;AAAA,MACjB,qBAAqB;AAAA,IACvB;AAAA,IACA,IAAI;AAAA,MACF,gBAAgB;AAAA,MAChB,iBAAiB;AAAA,MACjB,gBAAgB;AAAA,MAChB,iBAAiB;AAAA,MACjB,eAAe;AAAA,MACf,QAAQ,IAAS,EAAE,UAAU,EAAE;AAAA,MAC/B,MAAM,IAAS,EAAE,UAAU,EAAE;AAAA,MAC7B,UAAU;AAAA,IACZ;AAAA,IACA,KAAK,EACH,cAAc,KAChB;AAAA,IACA,SAAS;AAAA,MACP,SAAS;AAAA,MACT,cAAc;AAAA,IAChB;AAAA,IACA,OAAO,EACL,gBAAgB,GAClB;AAAA,IACA,OAAO;AAAA,MACL,eAAe;AAAA,MACf,UAAU;AAAA,MACV,SAAS;AAAA,MACT,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ,WAAW;AAAA,MACX,YAAY;AAAA,MACZ,aAAa;AAAA,MACb,gBAAgB;AAAA,MAChB,UAAU;AAAA,MACV,aAAa;AAAA,MACb,kBAAkB;AAAA,MAClB,mBAAmB;AAAA,MACnB,QAAQ;AAAA,IACV;AAAA,EACF;AACF;AC/RA,SAAS,EAAmB,GAAmD;AAC7E,SAAO,OAAO,KAAc,YAC1B,OAAO,SAAS,CAAS,KACzB,KAAa,IACX,IACA;AACN;AAaA,IAAM,IAAsC;AAAA,EAAE,GAAG;AAAA,EAAG,GAAG;AAAA,EAAG,OAAO;AAAE;AAEnE,SAAS,EAAa,GAAqB;AACzC,SAAO,oCAAoC,mBAAmB,CAAG,CAAA;AACnE;AAMA,SAAS,EAAgB,EAAE,WAAA,EAAA,GAAqC;AAC9D,SACE,gBAAA,EAAC,OAAD;AAAA,IACE,WAAU;AAAA,IACV,OAAO;AAAA,MAAE,WAAW;AAAA,MAAK,WAAA;AAAA,IAAU;AAAA,cAEnC,gBAAA,EAAC,OAAD;AAAA,MAAK,WAAU;AAAA,gBAAf;AAAA,QACE,gBAAA,EAAC,GAAD,EAAU,WAAU,YAAa,CAAA;AAAA,QACjC,gBAAA,EAAC,OAAD;AAAA,UAAK,WAAU;AAAA,oBAAf;AAAA,YACE,gBAAA,EAAC,GAAD,EAAU,WAAU,uBAAwB,CAAA;AAAA,YAC5C,gBAAA,EAAC,GAAD,EAAU,WAAU,UAAW,CAAA;AAAA,YAC/B,gBAAA,EAAC,GAAD,EAAU,WAAU,uBAAwB,CAAA;AAAA,YAC5C,gBAAA,EAAC,GAAD,EAAU,WAAU,UAAW,CAAA;AAAA,YAC/B,gBAAA,EAAC,GAAD,EAAU,WAAU,uBAAwB,CAAA;AAAA,UACzC;AAAA;QACL,gBAAA,EAAC,GAAD,EAAU,WAAU,YAAa,CAAA;AAAA,MAC9B;AAAA;EACF,CAAA;AAET;AAWA,SAAS,EAAa,EAAE,MAAA,GAAM,OAAA,EAAA,GAA4B;AACxD,SACE,gBAAA,EAAC,OAAD;AAAA,IAAK,WAAU;AAAA,cAAf,CACE,gBAAA,EAAC,OAAD;AAAA,MACE,WAAU;AAAA,MACV,MAAK;AAAA,gBAFP;AAAA,QAIE,gBAAA,EAAC,OAAD;AAAA,UACE,OAAM;AAAA,UACN,SAAQ;AAAA,UACR,MAAK;AAAA,UACL,WAAU;AAAA,UACV,eAAY;AAAA,oBAEZ,gBAAA,EAAC,QAAD;AAAA,YACE,UAAS;AAAA,YACT,GAAE;AAAA,YACF,UAAS;AAAA,UACV,CAAA;AAAA,QACE,CAAA;AAAA,QACL,gBAAA,EAAC,QAAD;AAAA,UAAM,WAAU;AAAA,oBAAc;AAAA,QAA0B,CAAA;AAAA,QACxD,gBAAA,EAAC,QAAD;AAAA,UAAM,WAAU;AAAA,oBAAY;AAAA,QAAY,CAAA;AAAA,MACrC;AAAA,QACL,gBAAA,EAAC,GAAD;AAAA,MAAmB,MAAA;AAAA,MAAM,UAAS;AAAA,MAAU,iBAAA;AAAA,IAAiB,CAAA,CAC1D;AAAA;AAET;AAMA,SAAS,EACP,GACkB;AAClB,SAAO,GAAe,gBAAgB,UAAU,SAAS,MAAM,IAC3D,SACA;AACN;AAEA,SAAS,GACP,GACA,GAC8B;AAC9B,QAAM,CAAC,GAAe,CAAA,IAAoB,EAAM,SAAA,MAEvC,MAAU,SAAS,SAAY,CAAM;AAE9C,SAAA,EAAM,UAAA,MAAgB;AACpB,QAAI,MAAU,QAAQ;AACpB,MAAA,EAAiB,CAAK;AACtB;AAAA,IACF;AAEA,UAAM,IAAgB,EAAS,SAAS,eAClC,IAAwB,GAAe,aAAa;AAC1D,QAAI,CAAC,KAAiB,CAAC,GAAuB;AAC5C,MAAA,EAAiB,OAAO;AACxB;AAAA,IACF;AAGA,UAAM,IAAW,IAAI,EAAA,MAA4B;AAC/C,MAAA,EAAiB,EAAiB,CAAa,CAAC;AAAA,IAClD,CAAC;AAED,WAAA,EAAS,QAAQ,EAAc,iBAAiB;AAAA,MAC9C,YAAY;AAAA,MACZ,iBAAiB,CAAC,OAAO;AAAA,IAC3B,CAAC,GAGD,EAAiB,EAAiB,CAAa,CAAC,GAEhD,MAAa,EAAS,WAAW;AAAA,EACnC,GAAG,CAAC,GAAO,CAAQ,CAAC,GAEb;AACT;AAOA,IAAI,KAAmB;AAEvB,SAAS,EAAiB,EACxB,MAAA,GACA,OAAA,IAAQ,QACR,SAAA,GACA,aAAA,IAAc,IACd,WAAA,GACA,WAAA,EAAA,GACwB;AACxB,QAAM,IAAgB,EAAmB,CAAS,GAC5C,CAAC,GAAY,CAAA,IAAiB,EAAM,SAAwB,IAAI,GAChE,CAAC,GAAO,CAAA,IAAY,EAAM,SAAwB,IAAI,GACtD,CAAC,GAAW,CAAA,IAAgB,EAAM,SAAS,EAAI,GAC/C,IAAW,EAAM,OAA2B,IAAI,GAChD,IAAe,EAAM,OAAuB,IAAI,GAChD,IAAgB,GAAiB,GAAO,CAAQ,GAChD,IAAQ,EAAM,OAAe,mBAAmB,EAAE,EAAA,EAAkB,GACpE,IAAe,EAAM,YAAA,CAAa,MAA6B;AACnE,IAAA,EAAS,UAAU;AAAA,EACrB,GAAG,CAAC,CAAC,GAGC,CAAC,GAAgB,CAAA,IACrB,EAAM,SAAA,OAAuC;AAAA,IAC3C,MAAA;AAAA,IACA,WAAW;AAAA,EACb,EAAE,GACE,CAAC,GAAY,CAAA,IAAiB,EAAM,SAAS,EAAK,GAClD,IAAe,EAAM,OAAO;AAAA,IAAE,GAAG;AAAA,IAAG,GAAG;AAAA,EAAE,CAAC;AAEhD,EAAA,EAAM,UAAA,MAAgB;AACpB,QAAI,CAAC,EACH;AAGF,UAAM,IAAc;AACpB,QAAI,IAAY;AAEhB,mBAAe,IAAgB;AAC7B,MAAA,EAAa,EAAI,GACjB,EAAS,IAAI,GACb,EAAc,IAAI;AAElB,UAAI;AAEF,cAAM,KAAW,MAAM,OAAO,mBAAA,GAAY,SAGpC,IAAS,EACb,GACA,EAAS,WAAW,EAAa,OACnC;AACA,QAAA,EAAQ,WAAW,CAAM;AAGzB,cAAM,IAAK,GAAG,EAAM,OAAA,IAAW,KAAK,IAAI,CAAA,IAIlC,EAAE,KAAA,EAAA,IAAQ,MAAM,EAAQ,OAAO,GAAI,EAAK,KAAK,CAAC;AAEpD,QAAK,MACH,EAAc,CAAG,GACjB,EAAS,IAAI;AAAA,MAEjB,SAAS,GAAK;AACZ,YAAI,CAAC,GAAW;AACd,gBAAM,IACJ,aAAe,QAAQ,EAAI,UAAU;AACvC,UAAA,EAAS,CAAY,GACrB,EAAc,IAAI;AAAA,QACpB;AAAA,MACF,UAAA;AACE,QAAK,KACH,EAAa,EAAK;AAAA,MAEtB;AAAA,IACF;AAEA,WAAA,EAAc,GAEd,MAAa;AACX,MAAA,IAAY;AAAA,IACd;AAAA,EACF,GAAG,CAAC,GAAM,CAAa,CAAC;AAExB,QAAM,IACJ,EAAe,SAAS,IAAO,EAAe,YAAY,GAEtD,IAAsB,EAAM,YAAA,CAE9B,MAGG;AACH,IAAA,EAAA,CAAmB,MAAY;AAC7B,YAAM,IACJ,EAAQ,SAAS,IAAO,EAAQ,YAAY;AAK9C,aAAO;AAAA,QAAE,MAAA;AAAA,QAAM,WAHb,OAAO,KAAkB,aACrB,EAAc,CAAgB,IAC9B;AAAA,MACmB;AAAA,IAC3B,CAAC;AAAA,EACH,GACA,CAAC,CAAI,CACP,GAGM,IAAc,EAAM,YAAA,CACvB,MAAwB;AACvB,QAAI,CAAC,EAAa;AAClB,IAAA,EAAE,eAAe;AAEjB,UAAM,IAAQ,EAAE,SAAS,IAAI,MAAM,KAC7B,IAAW,KAAK,IAAI,KAAK,IAAI,EAAU,QAAQ,GAAO,GAAG,GAAG,CAAC;AAEnE,IAAA,EAAA,CAAqB,OAAU;AAAA,MAC7B,GAAG;AAAA,MACH,OAAO;AAAA,IACT,EAAE;AAAA,EACJ,GACA;AAAA,IAAC;AAAA,IAAa;AAAA,IAAqB,EAAU;AAAA,EAAK,CACpD,GAEM,IAAkB,EAAM,YAAA,CAC3B,MAAwB;AACvB,IAAK,MACL,EAAc,EAAI,GAClB,EAAa,UAAU;AAAA,MACrB,GAAG,EAAE,UAAU,EAAU;AAAA,MACzB,GAAG,EAAE,UAAU,EAAU;AAAA,IAC3B;AAAA,EACF,GACA;AAAA,IAAC;AAAA,IAAa,EAAU;AAAA,IAAG,EAAU;AAAA,EAAC,CACxC,GAEM,IAAkB,EAAM,YAAA,CAC3B,MAAwB;AACvB,IAAI,CAAC,KAAc,CAAC,KACpB,EAAA,CAAqB,OAAU;AAAA,MAC7B,GAAG;AAAA,MACH,GAAG,EAAE,UAAU,EAAa,QAAQ;AAAA,MACpC,GAAG,EAAE,UAAU,EAAa,QAAQ;AAAA,IACtC,EAAE;AAAA,EACJ,GACA;AAAA,IAAC;AAAA,IAAY;AAAA,IAAa;AAAA,EAAmB,CAC/C,GAEM,IAAgB,EAAM,YAAA,MAAkB;AAC5C,IAAA,EAAc,EAAK;AAAA,EACrB,GAAG,CAAC,CAAC,GAEC,IAAc,EAAM,YAAA,MAAkB;AAC1C,IAAA,EAAoB,CAAiB;AAAA,EACvC,GAAG,CAAC,CAAmB,CAAC;AAGxB,MAAI,EACF,QACE,gBAAA,EAAC,OAAD;AAAA,IAAK,KAAK;AAAA,IAAc,aAAU;AAAA,cAChC,gBAAA,EAAC,GAAD,EAAiB,WAAW,EAAgB,CAAA;AAAA,EACzC,CAAA;AAKT,MAAI,EACF,QACE,gBAAA,EAAC,OAAD;AAAA,IAAK,KAAK;AAAA,IAAc,aAAU;AAAA,cAChC,gBAAA,EAAC,GAAD;AAAA,MAAoB,MAAA;AAAA,MAAa,OAAA;AAAA,IAAQ,CAAA;AAAA,EACtC,CAAA;AAKT,MAAI,CAAC,EACH,QACE,gBAAA,EAAC,OAAD;AAAA,IAAK,KAAK;AAAA,IAAc,aAAU;AAAA,cAChC,gBAAA,EAAC,GAAD,EAAiB,WAAW,EAAgB,CAAA;AAAA,EACzC,CAAA;AAGT,QAAM,IAAa,EAAa,CAAU;AAE1C,SACE,gBAAA,EAAC,UAAD;AAAA,IACE,KAAK;AAAA,IACL,aAAU;AAAA,IACV,WAAW,EAAG,aAAa,CAAS;AAAA,cAHtC,CAME,gBAAA,EAAC,OAAD;AAAA,MACE,KAAK;AAAA,MACL,WAAW,EACT,qEACA,KAAe,eACf,KAAc,iBAChB;AAAA,MACA,OAAO,EAAE,WAAW,EAAc;AAAA,MAClC,SAAS;AAAA,MACT,aAAa;AAAA,MACb,aAAa;AAAA,MACb,WAAW;AAAA,MACX,cAAc;AAAA,gBAZhB,CAeE,gBAAA,EAAC,OAAD;AAAA,QACE,WAAW,EACT,wCACA,MAAkB,UAAa,eACjC;AAAA,QACA,GAAK,MAAkB,SACnB;AAAA,UAAE,UAAU;AAAA,UAAG,MAAM;AAAA,UAAU,cAAc;AAAA,QAAe,IAC5D,CAAC;AAAA,QACL,OACE,IACI;AAAA,UACE,WAAW,aAAa,EAAU,CAAA,OAAQ,EAAU,CAAA,aAAc,EAAU,KAAA;AAAA,UAC5E,iBAAiB;AAAA,UACjB,YAAY,IAAa,SAAS;AAAA,QACpC,IACA;AAAA,kBAGN,gBAAA,EAAC,OAAD;AAAA,UACE,KAAK;AAAA,UACL,KAAI;AAAA,UACJ,WAAU;AAAA,UACV,WAAW;AAAA,QACZ,CAAA;AAAA,MACE,CAAA,GAGJ,KACC,gBAAA,EAAC,OAAD;AAAA,QAAK,WAAU;AAAA,kBAAf;AAAA,UACE,gBAAA,EAAC,UAAD;AAAA,YACE,MAAK;AAAA,YACL,SAAA,MACE,EAAA,CAAqB,OAAU;AAAA,cAC7B,GAAG;AAAA,cACH,OAAO,KAAK,IAAI,EAAK,QAAQ,KAAK,CAAC;AAAA,YACrC,EAAE;AAAA,YAEJ,WAAU;AAAA,YACV,cAAW;AAAA,sBAEX,gBAAA,EAAC,OAAD;AAAA,cACE,OAAM;AAAA,cACN,SAAQ;AAAA,cACR,MAAK;AAAA,cACL,WAAU;AAAA,wBAEV,gBAAA,EAAC,QAAD,EAAM,GAAE,wHAAyH,CAAA;AAAA,YAC9H,CAAA;AAAA,UACC,CAAA;AAAA,UACR,gBAAA,EAAC,UAAD;AAAA,YACE,MAAK;AAAA,YACL,SAAA,MACE,EAAA,CAAqB,OAAU;AAAA,cAC7B,GAAG;AAAA,cACH,OAAO,KAAK,IAAI,EAAK,QAAQ,KAAK,GAAG;AAAA,YACvC,EAAE;AAAA,YAEJ,WAAU;AAAA,YACV,cAAW;AAAA,sBAEX,gBAAA,EAAC,OAAD;AAAA,cACE,OAAM;AAAA,cACN,SAAQ;AAAA,cACR,MAAK;AAAA,cACL,WAAU;AAAA,wBAEV,gBAAA,EAAC,QAAD;AAAA,gBACE,UAAS;AAAA,gBACT,GAAE;AAAA,gBACF,UAAS;AAAA,cACV,CAAA;AAAA,YACE,CAAA;AAAA,UACC,CAAA;AAAA,UACR,gBAAA,EAAC,OAAD,EAAK,WAAU,sCAAuC,CAAA;AAAA,UACtD,gBAAA,EAAC,UAAD;AAAA,YACE,MAAK;AAAA,YACL,SAAS;AAAA,YACT,WAAU;AAAA,YACV,cAAW;AAAA,sBAEX,gBAAA,EAAC,OAAD;AAAA,cACE,OAAM;AAAA,cACN,SAAQ;AAAA,cACR,MAAK;AAAA,cACL,WAAU;AAAA,wBAEV,gBAAA,EAAC,QAAD;AAAA,gBACE,UAAS;AAAA,gBACT,GAAE;AAAA,gBACF,UAAS;AAAA,cACV,CAAA;AAAA,YACE,CAAA;AAAA,UACC,CAAA;AAAA,UACR,gBAAA,EAAC,QAAD;AAAA,YAAM,WAAU;AAAA,sBAAhB,CACG,KAAK,MAAM,EAAU,QAAQ,GAAG,GAAE,GAC/B;AAAA;QACH;AAAA,QAEJ;AAAA,QAGJ,KACC,gBAAA,EAAC,cAAD;AAAA,MAAY,WAAU;AAAA,gBACnB;AAAA,IACS,CAAA,CAER;AAAA;AAEZ;AAEA,EAAiB,cAAc"}
|
|
@@ -73,7 +73,7 @@ I.displayName = "AIMessage.Reactions";
|
|
|
73
73
|
function w({ onClick: e, active: a, className: t }) {
|
|
74
74
|
return /* @__PURE__ */ s(v, {
|
|
75
75
|
icon: /* @__PURE__ */ s(_, {
|
|
76
|
-
className: "size-4 text-
|
|
76
|
+
className: "size-4 text-muted-foreground",
|
|
77
77
|
"aria-hidden": "true"
|
|
78
78
|
}),
|
|
79
79
|
onClick: e,
|
|
@@ -86,7 +86,7 @@ w.displayName = "AIMessage.ThumbsUp";
|
|
|
86
86
|
function M({ onClick: e, active: a, className: t }) {
|
|
87
87
|
return /* @__PURE__ */ s(v, {
|
|
88
88
|
icon: /* @__PURE__ */ s(Z, {
|
|
89
|
-
className: "size-4 text-
|
|
89
|
+
className: "size-4 text-muted-foreground",
|
|
90
90
|
"aria-hidden": "true"
|
|
91
91
|
}),
|
|
92
92
|
onClick: e,
|
|
@@ -294,7 +294,7 @@ var U = P(({ type: e = "received", isAgent: a = !1, compact: t = !1, isTyping: n
|
|
|
294
294
|
});
|
|
295
295
|
});
|
|
296
296
|
U.displayName = "AIMessage.Root";
|
|
297
|
-
var E = P(({ type: e = "received", content: a, senderName: t, timestamp: n, avatar: r, isAgent: i = !1, compact: d = !1, isTyping: l = !1, markdown: m, onInteraction: f, attachments: p, reactions: g, showActions: h = !1, onThumbsUp: y, onThumbsDown: x, onCopy: A, onShowList: L, onReactionClick: F, onAttachmentClick: H, thumbsUpActive:
|
|
297
|
+
var E = P(({ type: e = "received", content: a, senderName: t, timestamp: n, avatar: r, isAgent: i = !1, compact: d = !1, isTyping: l = !1, markdown: m, onInteraction: f, attachments: p, reactions: g, showActions: h = !1, onThumbsUp: y, onThumbsDown: x, onCopy: A, onShowList: L, onReactionClick: F, onAttachmentClick: H, thumbsUpActive: O, thumbsDownActive: W, className: Y, ...q }, G) => /* @__PURE__ */ u(U, {
|
|
298
298
|
ref: G,
|
|
299
299
|
type: e,
|
|
300
300
|
isAgent: i,
|
|
@@ -304,10 +304,10 @@ var E = P(({ type: e = "received", content: a, senderName: t, timestamp: n, avat
|
|
|
304
304
|
onThumbsDown: x,
|
|
305
305
|
onCopy: A,
|
|
306
306
|
onShowList: L,
|
|
307
|
-
thumbsUpActive:
|
|
308
|
-
thumbsDownActive:
|
|
309
|
-
className:
|
|
310
|
-
...
|
|
307
|
+
thumbsUpActive: O,
|
|
308
|
+
thumbsDownActive: W,
|
|
309
|
+
className: Y,
|
|
310
|
+
...q,
|
|
311
311
|
children: [
|
|
312
312
|
e !== "sent" && !d && r && (c.isValidElement(r) ? r : /* @__PURE__ */ s(B, {
|
|
313
313
|
...r,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AIMessage.js","names":[],"sources":["../../src/components/organisms/ai/AIMessage/AIMessage.tsx"],"sourcesContent":["import { cva, type VariantProps } from 'class-variance-authority';\nimport { Check, Copy, List, ThumbsDown, ThumbsUp } from 'lucide-react';\nimport * as React from 'react';\nimport { forwardRef, type HTMLAttributes } from 'react';\nimport { Avatar, type AvatarProps } from '@/components/molecules/data/Avatar';\nimport { FileTypeIcon } from '@/components/molecules/files/FileTypeIcon';\nimport type { AIInteractionEvent } from '@/components/organisms/ai/_shared/interaction-context';\nimport { AIInteractionProvider } from '@/components/organisms/ai/_shared/interaction-context';\nimport { MarkdownRenderer } from '@/components/organisms/ai/_shared/markdown-renderer';\nimport { AITypingIndicator } from '@/components/organisms/ai/AITypingIndicator';\nimport { createSafeContext } from '@/lib/create-safe-context';\nimport { cn } from '@/lib/utils';\n\n// =============================================================================\n// Message Variants\n// =============================================================================\n\nconst messageVariants = cva('flex items-start w-full', {\n variants: {\n type: {\n received: 'justify-start',\n sent: 'justify-end',\n },\n },\n defaultVariants: {\n type: 'received',\n },\n});\n\nconst messageOverflowWrapClasses =\n 'min-w-0 max-w-full break-words [overflow-wrap:anywhere]';\n\nconst messageBubbleVariants = cva(\n 'flex min-w-0 max-w-[min(720px,100%)] flex-col gap-1 overflow-hidden px-4 py-3 rounded-2xl',\n {\n variants: {\n type: {\n received: 'bg-muted rounded-es-sm',\n sent: 'bg-primary text-primary-foreground rounded-ee-sm',\n },\n },\n defaultVariants: {\n type: 'received',\n },\n },\n);\n\n// =============================================================================\n// Context for Composable API\n// =============================================================================\n\ninterface AIMessageContextValue {\n /** Message type */\n type: 'received' | 'sent';\n /** Whether sender is an AI agent */\n isAgent: boolean;\n /** Whether in compact mode */\n compact: boolean;\n /** Whether AI is typing */\n isTyping: boolean;\n /** Callback when thumbs up is clicked */\n onThumbsUp?: () => void;\n /** Callback when thumbs down is clicked */\n onThumbsDown?: () => void;\n /** Callback when copy is clicked */\n onCopy?: () => void;\n /** Callback when list/expand is clicked */\n onShowList?: () => void;\n /** Whether thumbs up is active */\n thumbsUpActive?: boolean;\n /** Whether thumbs down is active */\n thumbsDownActive?: boolean;\n}\n\nconst [AIMessageContext, useAIMessageContext] =\n createSafeContext<AIMessageContextValue>('AIMessage');\n\n// =============================================================================\n// AIMessage.Bubble - Bubble wrapper for header + content\n// =============================================================================\n\nexport interface AIMessageBubbleProps {\n /** Children (Header, Content, TypingIndicator) */\n children?: React.ReactNode;\n /** Additional class name */\n className?: string;\n}\n\nfunction AIMessageBubble({ children, className }: AIMessageBubbleProps) {\n const ctx = React.useContext(AIMessageContext);\n const type = ctx?.type ?? 'received';\n\n return (\n <div\n data-slot=\"ai-message-bubble\"\n data-message-type={type}\n className={cn(messageBubbleVariants({ type }), className)}\n >\n {children}\n </div>\n );\n}\n\nAIMessageBubble.displayName = 'AIMessage.Bubble';\n\n// =============================================================================\n// Reaction Button (Internal)\n// =============================================================================\n\ninterface ReactionButtonProps {\n icon: React.ReactNode;\n onClick?: () => void;\n active?: boolean;\n count?: number;\n /** Accessible label for the button */\n label?: string;\n className?: string;\n}\n\nfunction ReactionButton({\n icon,\n onClick,\n active,\n count,\n label,\n className,\n}: ReactionButtonProps) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n aria-label={label}\n aria-pressed={active}\n className={cn(\n 'flex items-center justify-center gap-1 px-2.5 py-2 min-w-11 min-h-11 rounded-full bg-muted hover:bg-accent delight-click-ripple transition-all duration-150 ease-out hover:scale-110 active:scale-95 motion-reduce:hover:scale-100 motion-reduce:active:scale-100 focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-ring',\n active &&\n 'bg-primary/10 text-primary delight-check-bounce motion-reduce:!animate-none',\n className,\n )}\n >\n {icon}\n {count !== undefined && count > 0 && (\n <span className=\"text-xs font-medium text-muted-foreground\">\n {count}\n </span>\n )}\n </button>\n );\n}\n\n// =============================================================================\n// Emoji Reaction Types\n// =============================================================================\n\nexport interface EmojiReaction {\n emoji: string;\n count: number;\n reacted?: boolean;\n}\n\n// =============================================================================\n// AIMessage.Reactions - Emoji reactions display\n// =============================================================================\n\nexport interface AIMessageReactionsProps {\n /** Emoji reactions to display */\n reactions: EmojiReaction[];\n /** Callback when reaction is clicked */\n onReactionClick?: (emoji: string) => void;\n /** Additional class name */\n className?: string;\n}\n\nfunction AIMessageReactions({\n reactions,\n onReactionClick,\n className,\n}: AIMessageReactionsProps) {\n if (!reactions?.length) return null;\n\n return (\n <div\n data-slot=\"ai-message-reactions\"\n className={cn('flex items-center gap-1', className)}\n >\n {reactions.map((reaction) => (\n <button\n key={reaction.emoji}\n type=\"button\"\n onClick={() => onReactionClick?.(reaction.emoji)}\n aria-label={`React with ${reaction.emoji}${reaction.count > 1 ? `, ${reaction.count} reactions` : ''}`}\n aria-pressed={reaction.reacted}\n className={cn(\n 'flex items-center gap-1 px-2.5 py-1.5 min-h-11 rounded-full bg-muted hover:bg-accent text-sm transition-colors focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-ring',\n reaction.reacted && 'bg-primary/10',\n )}\n >\n <span aria-hidden=\"true\">{reaction.emoji}</span>\n {reaction.count > 1 && (\n <span className=\"text-xs text-muted-foreground\">\n {reaction.count}\n </span>\n )}\n </button>\n ))}\n </div>\n );\n}\n\nAIMessageReactions.displayName = 'AIMessage.Reactions';\n\n// =============================================================================\n// AIMessage.ThumbsUp - Thumbs up button\n// =============================================================================\n\nexport interface AIMessageThumbsUpProps {\n /** Click handler */\n onClick?: () => void;\n /** Whether active */\n active?: boolean;\n /** Additional class name */\n className?: string;\n}\n\nfunction AIMessageThumbsUp({\n onClick,\n active,\n className,\n}: AIMessageThumbsUpProps) {\n return (\n <ReactionButton\n icon={\n <ThumbsUp className=\"size-4 text-text-quaternary\" aria-hidden=\"true\" />\n }\n onClick={onClick}\n active={active}\n label=\"Thumbs up\"\n className={className}\n />\n );\n}\n\nAIMessageThumbsUp.displayName = 'AIMessage.ThumbsUp';\n\n// =============================================================================\n// AIMessage.ThumbsDown - Thumbs down button\n// =============================================================================\n\nexport interface AIMessageThumbsDownProps {\n /** Click handler */\n onClick?: () => void;\n /** Whether active */\n active?: boolean;\n /** Additional class name */\n className?: string;\n}\n\nfunction AIMessageThumbsDown({\n onClick,\n active,\n className,\n}: AIMessageThumbsDownProps) {\n return (\n <ReactionButton\n icon={\n <ThumbsDown\n className=\"size-4 text-text-quaternary\"\n aria-hidden=\"true\"\n />\n }\n onClick={onClick}\n active={active}\n label=\"Thumbs down\"\n className={className}\n />\n );\n}\n\nAIMessageThumbsDown.displayName = 'AIMessage.ThumbsDown';\n\n// =============================================================================\n// AIMessage.CopyButton - Copy button\n// =============================================================================\n\nexport interface AIMessageCopyButtonProps {\n /** Click handler */\n onClick?: () => void;\n /** Additional class name */\n className?: string;\n}\n\nfunction AIMessageCopyButton({ onClick, className }: AIMessageCopyButtonProps) {\n const [copied, setCopied] = React.useState(false);\n const timerRef = React.useRef<ReturnType<typeof setTimeout>>(undefined);\n\n React.useEffect(() => () => clearTimeout(timerRef.current), []);\n\n const handleClick = React.useCallback(() => {\n onClick?.();\n setCopied(true);\n clearTimeout(timerRef.current);\n timerRef.current = setTimeout(() => setCopied(false), 2000);\n }, [onClick]);\n\n return (\n <ReactionButton\n icon={\n copied ? (\n <Check\n className=\"size-4 text-success delight-bounce-in motion-reduce:animate-none\"\n aria-hidden=\"true\"\n />\n ) : (\n <Copy\n className=\"size-4 text-secondary-foreground\"\n aria-hidden=\"true\"\n />\n )\n }\n onClick={handleClick}\n label={copied ? 'Copied to clipboard' : 'Copy message'}\n className={className}\n />\n );\n}\n\nAIMessageCopyButton.displayName = 'AIMessage.CopyButton';\n\n// =============================================================================\n// AIMessage.ListButton - List/expand button\n// =============================================================================\n\nexport interface AIMessageListButtonProps {\n /** Click handler */\n onClick?: () => void;\n /** Additional class name */\n className?: string;\n}\n\nfunction AIMessageListButton({ onClick, className }: AIMessageListButtonProps) {\n return (\n <ReactionButton\n icon={\n <List className=\"size-4 text-secondary-foreground\" aria-hidden=\"true\" />\n }\n onClick={onClick}\n label=\"Show list\"\n className={className}\n />\n );\n}\n\nAIMessageListButton.displayName = 'AIMessage.ListButton';\n\n// =============================================================================\n// AIMessage.Actions - Action toolbar container\n// =============================================================================\n\nexport interface AIMessageActionsProps {\n /** Children (action buttons) */\n children?: React.ReactNode;\n /** Additional class name */\n className?: string;\n}\n\nfunction AIMessageActions({ children, className }: AIMessageActionsProps) {\n const ctx = React.useContext(AIMessageContext);\n\n return (\n <div\n data-slot=\"ai-message-actions\"\n role=\"toolbar\"\n aria-label=\"Message actions\"\n className={cn(\n 'flex items-center gap-0.5 rounded-full overflow-hidden',\n className,\n )}\n >\n {children ??\n (ctx && (\n <>\n <AIMessageThumbsUp\n onClick={ctx.onThumbsUp}\n active={ctx.thumbsUpActive}\n />\n <AIMessageThumbsDown\n onClick={ctx.onThumbsDown}\n active={ctx.thumbsDownActive}\n />\n <AIMessageCopyButton onClick={ctx.onCopy} />\n <AIMessageListButton onClick={ctx.onShowList} />\n </>\n ))}\n </div>\n );\n}\n\nAIMessageActions.displayName = 'AIMessage.Actions';\n\n// =============================================================================\n// AIMessage.TypingIndicator - Bouncing dots\n// =============================================================================\n\nexport interface AIMessageTypingIndicatorProps {\n /** Additional class name */\n className?: string;\n}\n\nfunction AIMessageTypingIndicator({\n className,\n}: AIMessageTypingIndicatorProps) {\n return (\n <div\n data-slot=\"ai-message-typing-indicator\"\n className={cn(\n 'flex items-center gap-1 motion-reduce:animate-none',\n className,\n )}\n >\n <AITypingIndicator size=\"sm\" color=\"var(--muted-foreground)\" />\n </div>\n );\n}\n\nAIMessageTypingIndicator.displayName = 'AIMessage.TypingIndicator';\n\n// =============================================================================\n// Attachment Types\n// =============================================================================\n\nexport interface Attachment {\n id: string;\n name: string;\n size: string;\n /** File extension (e.g., 'pdf', 'jpg', 'doc') */\n extension?: string;\n url?: string;\n thumbnailUrl?: string;\n}\n\n// =============================================================================\n// AIMessage.AttachmentPreview - Single attachment preview\n// =============================================================================\n\nexport interface AIMessageAttachmentPreviewProps {\n /** Attachment data */\n attachment: Attachment;\n /** Message type for styling */\n messageType?: 'received' | 'sent';\n /** Click handler */\n onClick?: () => void;\n /** Additional class name */\n className?: string;\n}\n\nfunction AIMessageAttachmentPreview({\n attachment,\n messageType = 'received',\n onClick,\n className,\n}: AIMessageAttachmentPreviewProps) {\n // Derive extension from attachment.extension or extract from filename\n const getExtension = () => {\n if (attachment.extension) {\n return attachment.extension;\n }\n const parts = attachment.name.split('.');\n if (parts.length > 1) {\n return parts[parts.length - 1];\n }\n return '';\n };\n\n const extension = getExtension();\n\n const bubbleClasses =\n messageType === 'sent'\n ? 'bg-primary/10 border border-primary-foreground/20 rounded-2xl'\n : 'bg-muted rounded-2xl';\n\n return (\n <button\n type=\"button\"\n data-slot=\"ai-message-attachment-preview\"\n onClick={onClick}\n aria-label={`Attachment: ${attachment.name}, ${attachment.size}`}\n className={cn(\n 'flex items-center gap-3 p-3 min-h-11 hover:bg-accent transition-colors w-full max-w-[320px] focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-ring',\n bubbleClasses,\n className,\n )}\n >\n {attachment.thumbnailUrl ? (\n <img\n src={attachment.thumbnailUrl}\n alt={attachment.name}\n className=\"size-10 rounded-md object-cover\"\n />\n ) : (\n <FileTypeIcon extension={extension} size=\"md\" className=\"shrink-0\" />\n )}\n <div className=\"flex flex-col items-start min-w-0\">\n <span className=\"text-sm font-medium text-secondary-foreground truncate w-full\">\n {attachment.name}\n </span>\n <span className=\"text-sm text-muted-foreground\">{attachment.size}</span>\n </div>\n </button>\n );\n}\n\nAIMessageAttachmentPreview.displayName = 'AIMessage.AttachmentPreview';\n\n// =============================================================================\n// AIMessage.Attachments - Attachments container\n// =============================================================================\n\nexport interface AIMessageAttachmentsProps {\n /** Attachments to display */\n attachments: Attachment[];\n /** Message type for styling */\n messageType?: 'received' | 'sent';\n /** Callback when attachment is clicked */\n onAttachmentClick?: (attachment: Attachment) => void;\n /** Additional class name */\n className?: string;\n}\n\nfunction AIMessageAttachments({\n attachments,\n messageType = 'received',\n onAttachmentClick,\n className,\n}: AIMessageAttachmentsProps) {\n if (!attachments?.length) return null;\n\n return (\n <div\n data-slot=\"ai-message-attachments\"\n className={cn('flex flex-col gap-2 mt-1', className)}\n >\n {attachments.map((attachment) => (\n <AIMessageAttachmentPreview\n key={attachment.id}\n attachment={attachment}\n messageType={messageType}\n onClick={() => onAttachmentClick?.(attachment)}\n />\n ))}\n </div>\n );\n}\n\nAIMessageAttachments.displayName = 'AIMessage.Attachments';\n\n// =============================================================================\n// AIMessage.Avatar - Avatar with agent indicator\n// =============================================================================\n\nexport interface AIMessageAvatarProps extends AvatarProps {\n /** Whether sender is an agent */\n isAgent?: boolean;\n}\n\nfunction AIMessageAvatar({ isAgent, ...props }: AIMessageAvatarProps) {\n return (\n <Avatar\n data-slot=\"ai-message-avatar\"\n {...props}\n size=\"md\"\n indicator={isAgent ? 'verified' : props.indicator}\n />\n );\n}\n\nAIMessageAvatar.displayName = 'AIMessage.Avatar';\n\n// =============================================================================\n// AIMessage.Content - Message content with markdown support\n// =============================================================================\n\nexport interface AIMessageContentProps {\n /** Message content */\n children?: React.ReactNode;\n /** Content as string (alternative to children) */\n content?: string;\n /** Whether to render content as markdown. Defaults to true for received, false for sent. */\n markdown?: boolean;\n /** Callback for interactive component events */\n onInteraction?: (event: AIInteractionEvent) => void;\n /** Additional class name */\n className?: string;\n}\n\nfunction AIMessageContent({\n children,\n content,\n markdown,\n onInteraction,\n className,\n}: AIMessageContentProps) {\n const ctx = React.useContext(AIMessageContext);\n const type = ctx?.type ?? 'received';\n const isSent = type === 'sent';\n\n const shouldRenderMarkdown = markdown ?? type === 'received';\n const textContent = content ?? (typeof children === 'string' ? children : '');\n const variant = isSent ? 'inverted' : 'default';\n\n return (\n <div\n data-slot=\"ai-message-content\"\n className={cn('w-full', messageOverflowWrapClasses, className)}\n >\n {shouldRenderMarkdown && textContent ? (\n <AIInteractionProvider onInteraction={onInteraction}>\n <MarkdownRenderer\n variant={variant}\n className={cn(\n 'text-base',\n isSent ? 'text-primary-foreground' : 'text-foreground',\n )}\n >\n {textContent}\n </MarkdownRenderer>\n </AIInteractionProvider>\n ) : textContent ? (\n <p\n className={cn(\n 'text-sm leading-5 whitespace-pre-wrap',\n messageOverflowWrapClasses,\n isSent ? 'text-primary-foreground' : 'text-foreground',\n )}\n >\n {textContent}\n </p>\n ) : (\n children\n )}\n </div>\n );\n}\n\nAIMessageContent.displayName = 'AIMessage.Content';\n\n// =============================================================================\n// AIMessage.Header - Header with name and timestamp\n// =============================================================================\n\nexport interface AIMessageHeaderProps {\n /** Sender name */\n senderName?: string;\n /** Timestamp string */\n timestamp?: string;\n /** Show avatar slot */\n avatar?: React.ReactNode;\n /** Additional class name */\n className?: string;\n}\n\nfunction AIMessageHeader({\n senderName,\n timestamp,\n avatar,\n className,\n}: AIMessageHeaderProps) {\n const ctx = React.useContext(AIMessageContext);\n const isSent = ctx?.type === 'sent';\n const compact = ctx?.compact ?? false;\n\n if (compact) return null;\n\n return (\n <div\n data-slot=\"ai-message-header\"\n className={cn('flex items-center justify-between w-full', className)}\n >\n <div className=\"flex items-center gap-2 min-w-0 flex-1\">\n {avatar && <div className=\"shrink-0\">{avatar}</div>}\n <span\n className={cn(\n 'text-sm font-medium truncate',\n isSent ? 'text-primary-foreground' : 'text-secondary-foreground',\n )}\n >\n {isSent ? (senderName ?? 'You') : senderName}\n </span>\n </div>\n {timestamp && (\n <span\n className={cn(\n 'text-xs shrink-0',\n isSent ? 'text-primary-foreground/90' : 'text-muted-foreground',\n )}\n >\n {timestamp}\n </span>\n )}\n </div>\n );\n}\n\nAIMessageHeader.displayName = 'AIMessage.Header';\n\n// =============================================================================\n// AIMessage.Root - Root container for composable API\n// =============================================================================\n\nexport interface AIMessageRootProps\n extends Omit<HTMLAttributes<HTMLDivElement>, 'content'> {\n /** Message type */\n type?: 'received' | 'sent';\n /** Whether sender is an AI agent */\n isAgent?: boolean;\n /** Whether in compact mode */\n compact?: boolean;\n /** Whether AI is typing */\n isTyping?: boolean;\n /** Callback when thumbs up is clicked */\n onThumbsUp?: () => void;\n /** Callback when thumbs down is clicked */\n onThumbsDown?: () => void;\n /** Callback when copy is clicked */\n onCopy?: () => void;\n /** Callback when list/expand is clicked */\n onShowList?: () => void;\n /** Whether thumbs up is active */\n thumbsUpActive?: boolean;\n /** Whether thumbs down is active */\n thumbsDownActive?: boolean;\n /** Children */\n children?: React.ReactNode;\n /** Additional class name */\n className?: string;\n}\n\nconst AIMessageRoot = forwardRef<HTMLDivElement, AIMessageRootProps>(\n (\n {\n type = 'received',\n isAgent = false,\n compact = false,\n isTyping = false,\n onThumbsUp,\n onThumbsDown,\n onCopy,\n onShowList,\n thumbsUpActive,\n thumbsDownActive,\n children,\n className,\n ...props\n },\n ref,\n ) => {\n const isSent = type === 'sent';\n\n const contextValue = React.useMemo<AIMessageContextValue>(\n () => ({\n type,\n isAgent,\n compact,\n isTyping,\n onThumbsUp,\n onThumbsDown,\n onCopy,\n onShowList,\n thumbsUpActive,\n thumbsDownActive,\n }),\n [\n type,\n isAgent,\n compact,\n isTyping,\n onThumbsUp,\n onThumbsDown,\n onCopy,\n onShowList,\n thumbsUpActive,\n thumbsDownActive,\n ],\n );\n\n return (\n <AIMessageContext.Provider value={contextValue}>\n <div\n ref={ref}\n data-slot=\"ai-message\"\n className={cn(\n messageVariants({ type }),\n isSent ? 'pe-2' : 'ps-0',\n isSent ? 'delight-slide-in-end' : 'delight-slide-up',\n className,\n )}\n {...props}\n >\n <div\n className={cn(\n 'flex min-w-0 max-w-full flex-col gap-1.5 items-start',\n isSent && 'items-end',\n )}\n >\n {children}\n </div>\n </div>\n </AIMessageContext.Provider>\n );\n },\n);\n\nAIMessageRoot.displayName = 'AIMessage.Root';\n\n// =============================================================================\n// Main AIMessage Component (Monolithic API)\n// =============================================================================\n\nexport interface AIMessageProps\n extends VariantProps<typeof messageVariants>,\n Omit<HTMLAttributes<HTMLDivElement>, 'content'> {\n /** Message type - 'received' for incoming, 'sent' for outgoing messages */\n type?: 'received' | 'sent';\n /** Message content */\n content?: string;\n /** Sender name */\n senderName?: string;\n /** Timestamp */\n timestamp?: string;\n /** Avatar — pass AvatarProps object or a React element */\n avatar?: AvatarProps | React.ReactElement;\n /** Whether the sender is an AI agent */\n isAgent?: boolean;\n /** Whether message is in compact mode (no avatar on subsequent messages) */\n compact?: boolean;\n /** Whether the AI is currently typing */\n isTyping?: boolean;\n /** Whether to render content as markdown. Defaults to true for received, false for sent. */\n markdown?: boolean;\n /** Callback when an interactive component triggers an interaction */\n onInteraction?: (event: AIInteractionEvent) => void;\n /** Attachments */\n attachments?: Attachment[];\n /** Emoji reactions */\n reactions?: EmojiReaction[];\n /** Whether to show action toolbar (for agent messages) */\n showActions?: boolean;\n /** Callback when thumbs up is clicked */\n onThumbsUp?: () => void;\n /** Callback when thumbs down is clicked */\n onThumbsDown?: () => void;\n /** Callback when copy is clicked */\n onCopy?: () => void;\n /** Callback when list/expand is clicked */\n onShowList?: () => void;\n /** Callback when emoji reaction is clicked */\n onReactionClick?: (emoji: string) => void;\n /** Callback when attachment is clicked */\n onAttachmentClick?: (attachment: Attachment) => void;\n /** Whether thumbs up is active */\n thumbsUpActive?: boolean;\n /** Whether thumbs down is active */\n thumbsDownActive?: boolean;\n /** Additional class name */\n className?: string;\n}\n\nconst AIMessageDefault = forwardRef<HTMLDivElement, AIMessageProps>(\n (\n {\n type = 'received',\n content,\n senderName,\n timestamp,\n avatar,\n isAgent = false,\n compact = false,\n isTyping = false,\n markdown,\n onInteraction,\n attachments,\n reactions,\n showActions = false,\n onThumbsUp,\n onThumbsDown,\n onCopy,\n onShowList,\n onReactionClick,\n onAttachmentClick,\n thumbsUpActive,\n thumbsDownActive,\n className,\n ...props\n },\n ref,\n ) => {\n return (\n <AIMessageRoot\n ref={ref}\n type={type}\n isAgent={isAgent}\n compact={compact}\n isTyping={isTyping}\n onThumbsUp={onThumbsUp}\n onThumbsDown={onThumbsDown}\n onCopy={onCopy}\n onShowList={onShowList}\n thumbsUpActive={thumbsUpActive}\n thumbsDownActive={thumbsDownActive}\n className={className}\n {...props}\n >\n {type !== 'sent' &&\n !compact &&\n avatar &&\n (React.isValidElement(avatar) ? (\n avatar\n ) : (\n <AIMessageAvatar {...(avatar as AvatarProps)} isAgent={isAgent} />\n ))}\n\n <AIMessageBubble>\n {(type !== 'sent' || senderName || timestamp) && (\n <AIMessageHeader senderName={senderName} timestamp={timestamp} />\n )}\n\n {isTyping ? (\n <AIMessageTypingIndicator />\n ) : (\n content && (\n <AIMessageContent\n content={content}\n markdown={markdown}\n onInteraction={onInteraction}\n />\n )\n )}\n </AIMessageBubble>\n\n {!isTyping && attachments && attachments.length > 0 && (\n <AIMessageAttachments\n attachments={attachments}\n messageType={type ?? 'received'}\n onAttachmentClick={onAttachmentClick}\n />\n )}\n\n {!isTyping && (showActions || reactions?.length) && (\n <div className=\"flex items-center gap-1\">\n {showActions && isAgent && <AIMessageActions />}\n {reactions && reactions.length > 0 && (\n <AIMessageReactions\n reactions={reactions}\n onReactionClick={onReactionClick}\n />\n )}\n </div>\n )}\n </AIMessageRoot>\n );\n },\n);\n\nAIMessageDefault.displayName = 'AIMessage';\n\n// =============================================================================\n// Compound Component (Dual-API via Object.assign)\n// =============================================================================\n\n/**\n * AIMessage - Dual-API component for AI chat messages.\n *\n * Supports two usage patterns:\n *\n * 1. **Monolithic API (batteries-included)**:\n * ```tsx\n * <AIMessage\n * content=\"Hello!\"\n * senderName=\"Assistant\"\n * avatar={{ src: '...' }}\n * isAgent\n * showActions\n * />\n * ```\n *\n * 2. **Composable API (full customization)**:\n * ```tsx\n * <AIMessage.Root type=\"received\" isAgent>\n * <AIMessage.Avatar src=\"...\" isAgent />\n * <AIMessage.Bubble>\n * <AIMessage.Header senderName=\"Assistant\" timestamp=\"Now\" />\n * <AIMessage.Content markdown>\n * Hello!\n * </AIMessage.Content>\n * </AIMessage.Bubble>\n * <AIMessage.Actions>\n * <AIMessage.ThumbsUp onClick={...} />\n * <AIMessage.ThumbsDown onClick={...} />\n * <AIMessage.CopyButton onClick={...} />\n * </AIMessage.Actions>\n * </AIMessage.Root>\n * ```\n */\nconst AIMessage = Object.assign(AIMessageDefault, {\n Root: AIMessageRoot,\n Bubble: AIMessageBubble,\n Header: AIMessageHeader,\n Avatar: AIMessageAvatar,\n Content: AIMessageContent,\n Actions: AIMessageActions,\n Reactions: AIMessageReactions,\n Attachments: AIMessageAttachments,\n AttachmentPreview: AIMessageAttachmentPreview,\n TypingIndicator: AIMessageTypingIndicator,\n CopyButton: AIMessageCopyButton,\n ThumbsUp: AIMessageThumbsUp,\n ThumbsDown: AIMessageThumbsDown,\n ListButton: AIMessageListButton,\n});\n\n// =============================================================================\n// Named Exports\n// =============================================================================\n\n// Type exports\nexport type { AIMessageRootProps as AIMessageComposableProps };\nexport {\n AIMessage,\n AIMessageActions,\n AIMessageAttachmentPreview,\n AIMessageAttachments,\n AIMessageAvatar,\n AIMessageBubble,\n AIMessageContent,\n AIMessageCopyButton,\n AIMessageHeader,\n AIMessageListButton,\n AIMessageReactions,\n // Composable subcomponents\n AIMessageRoot,\n AIMessageThumbsDown,\n AIMessageThumbsUp,\n AIMessageTypingIndicator,\n // Variants\n messageBubbleVariants,\n messageVariants,\n // Context hook for custom subcomponents\n useAIMessageContext,\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AIMessage.js","names":[],"sources":["../../src/components/organisms/ai/AIMessage/AIMessage.tsx"],"sourcesContent":["import { cva, type VariantProps } from 'class-variance-authority';\nimport { Check, Copy, List, ThumbsDown, ThumbsUp } from 'lucide-react';\nimport * as React from 'react';\nimport { forwardRef, type HTMLAttributes } from 'react';\nimport { Avatar, type AvatarProps } from '@/components/molecules/data/Avatar';\nimport { FileTypeIcon } from '@/components/molecules/files/FileTypeIcon';\nimport type { AIInteractionEvent } from '@/components/organisms/ai/_shared/interaction-context';\nimport { AIInteractionProvider } from '@/components/organisms/ai/_shared/interaction-context';\nimport { MarkdownRenderer } from '@/components/organisms/ai/_shared/markdown-renderer';\nimport { AITypingIndicator } from '@/components/organisms/ai/AITypingIndicator';\nimport { createSafeContext } from '@/lib/create-safe-context';\nimport { cn } from '@/lib/utils';\n\n// =============================================================================\n// Message Variants\n// =============================================================================\n\nconst messageVariants = cva('flex items-start w-full', {\n variants: {\n type: {\n received: 'justify-start',\n sent: 'justify-end',\n },\n },\n defaultVariants: {\n type: 'received',\n },\n});\n\nconst messageOverflowWrapClasses =\n 'min-w-0 max-w-full break-words [overflow-wrap:anywhere]';\n\nconst messageBubbleVariants = cva(\n 'flex min-w-0 max-w-[min(720px,100%)] flex-col gap-1 overflow-hidden px-4 py-3 rounded-2xl',\n {\n variants: {\n type: {\n received: 'bg-muted rounded-es-sm',\n sent: 'bg-primary text-primary-foreground rounded-ee-sm',\n },\n },\n defaultVariants: {\n type: 'received',\n },\n },\n);\n\n// =============================================================================\n// Context for Composable API\n// =============================================================================\n\ninterface AIMessageContextValue {\n /** Message type */\n type: 'received' | 'sent';\n /** Whether sender is an AI agent */\n isAgent: boolean;\n /** Whether in compact mode */\n compact: boolean;\n /** Whether AI is typing */\n isTyping: boolean;\n /** Callback when thumbs up is clicked */\n onThumbsUp?: () => void;\n /** Callback when thumbs down is clicked */\n onThumbsDown?: () => void;\n /** Callback when copy is clicked */\n onCopy?: () => void;\n /** Callback when list/expand is clicked */\n onShowList?: () => void;\n /** Whether thumbs up is active */\n thumbsUpActive?: boolean;\n /** Whether thumbs down is active */\n thumbsDownActive?: boolean;\n}\n\nconst [AIMessageContext, useAIMessageContext] =\n createSafeContext<AIMessageContextValue>('AIMessage');\n\n// =============================================================================\n// AIMessage.Bubble - Bubble wrapper for header + content\n// =============================================================================\n\nexport interface AIMessageBubbleProps {\n /** Children (Header, Content, TypingIndicator) */\n children?: React.ReactNode;\n /** Additional class name */\n className?: string;\n}\n\nfunction AIMessageBubble({ children, className }: AIMessageBubbleProps) {\n const ctx = React.useContext(AIMessageContext);\n const type = ctx?.type ?? 'received';\n\n return (\n <div\n data-slot=\"ai-message-bubble\"\n data-message-type={type}\n className={cn(messageBubbleVariants({ type }), className)}\n >\n {children}\n </div>\n );\n}\n\nAIMessageBubble.displayName = 'AIMessage.Bubble';\n\n// =============================================================================\n// Reaction Button (Internal)\n// =============================================================================\n\ninterface ReactionButtonProps {\n icon: React.ReactNode;\n onClick?: () => void;\n active?: boolean;\n count?: number;\n /** Accessible label for the button */\n label?: string;\n className?: string;\n}\n\nfunction ReactionButton({\n icon,\n onClick,\n active,\n count,\n label,\n className,\n}: ReactionButtonProps) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n aria-label={label}\n aria-pressed={active}\n className={cn(\n 'flex items-center justify-center gap-1 px-2.5 py-2 min-w-11 min-h-11 rounded-full bg-muted hover:bg-accent delight-click-ripple transition-all duration-150 ease-out hover:scale-110 active:scale-95 motion-reduce:hover:scale-100 motion-reduce:active:scale-100 focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-ring',\n active &&\n 'bg-primary/10 text-primary delight-check-bounce motion-reduce:!animate-none',\n className,\n )}\n >\n {icon}\n {count !== undefined && count > 0 && (\n <span className=\"text-xs font-medium text-muted-foreground\">\n {count}\n </span>\n )}\n </button>\n );\n}\n\n// =============================================================================\n// Emoji Reaction Types\n// =============================================================================\n\nexport interface EmojiReaction {\n emoji: string;\n count: number;\n reacted?: boolean;\n}\n\n// =============================================================================\n// AIMessage.Reactions - Emoji reactions display\n// =============================================================================\n\nexport interface AIMessageReactionsProps {\n /** Emoji reactions to display */\n reactions: EmojiReaction[];\n /** Callback when reaction is clicked */\n onReactionClick?: (emoji: string) => void;\n /** Additional class name */\n className?: string;\n}\n\nfunction AIMessageReactions({\n reactions,\n onReactionClick,\n className,\n}: AIMessageReactionsProps) {\n if (!reactions?.length) return null;\n\n return (\n <div\n data-slot=\"ai-message-reactions\"\n className={cn('flex items-center gap-1', className)}\n >\n {reactions.map((reaction) => (\n <button\n key={reaction.emoji}\n type=\"button\"\n onClick={() => onReactionClick?.(reaction.emoji)}\n aria-label={`React with ${reaction.emoji}${reaction.count > 1 ? `, ${reaction.count} reactions` : ''}`}\n aria-pressed={reaction.reacted}\n className={cn(\n 'flex items-center gap-1 px-2.5 py-1.5 min-h-11 rounded-full bg-muted hover:bg-accent text-sm transition-colors focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-ring',\n reaction.reacted && 'bg-primary/10',\n )}\n >\n <span aria-hidden=\"true\">{reaction.emoji}</span>\n {reaction.count > 1 && (\n <span className=\"text-xs text-muted-foreground\">\n {reaction.count}\n </span>\n )}\n </button>\n ))}\n </div>\n );\n}\n\nAIMessageReactions.displayName = 'AIMessage.Reactions';\n\n// =============================================================================\n// AIMessage.ThumbsUp - Thumbs up button\n// =============================================================================\n\nexport interface AIMessageThumbsUpProps {\n /** Click handler */\n onClick?: () => void;\n /** Whether active */\n active?: boolean;\n /** Additional class name */\n className?: string;\n}\n\nfunction AIMessageThumbsUp({\n onClick,\n active,\n className,\n}: AIMessageThumbsUpProps) {\n return (\n <ReactionButton\n icon={\n <ThumbsUp className=\"size-4 text-muted-foreground\" aria-hidden=\"true\" />\n }\n onClick={onClick}\n active={active}\n label=\"Thumbs up\"\n className={className}\n />\n );\n}\n\nAIMessageThumbsUp.displayName = 'AIMessage.ThumbsUp';\n\n// =============================================================================\n// AIMessage.ThumbsDown - Thumbs down button\n// =============================================================================\n\nexport interface AIMessageThumbsDownProps {\n /** Click handler */\n onClick?: () => void;\n /** Whether active */\n active?: boolean;\n /** Additional class name */\n className?: string;\n}\n\nfunction AIMessageThumbsDown({\n onClick,\n active,\n className,\n}: AIMessageThumbsDownProps) {\n return (\n <ReactionButton\n icon={\n <ThumbsDown\n className=\"size-4 text-muted-foreground\"\n aria-hidden=\"true\"\n />\n }\n onClick={onClick}\n active={active}\n label=\"Thumbs down\"\n className={className}\n />\n );\n}\n\nAIMessageThumbsDown.displayName = 'AIMessage.ThumbsDown';\n\n// =============================================================================\n// AIMessage.CopyButton - Copy button\n// =============================================================================\n\nexport interface AIMessageCopyButtonProps {\n /** Click handler */\n onClick?: () => void;\n /** Additional class name */\n className?: string;\n}\n\nfunction AIMessageCopyButton({ onClick, className }: AIMessageCopyButtonProps) {\n const [copied, setCopied] = React.useState(false);\n const timerRef = React.useRef<ReturnType<typeof setTimeout>>(undefined);\n\n React.useEffect(() => () => clearTimeout(timerRef.current), []);\n\n const handleClick = React.useCallback(() => {\n onClick?.();\n setCopied(true);\n clearTimeout(timerRef.current);\n timerRef.current = setTimeout(() => setCopied(false), 2000);\n }, [onClick]);\n\n return (\n <ReactionButton\n icon={\n copied ? (\n <Check\n className=\"size-4 text-success delight-bounce-in motion-reduce:animate-none\"\n aria-hidden=\"true\"\n />\n ) : (\n <Copy\n className=\"size-4 text-secondary-foreground\"\n aria-hidden=\"true\"\n />\n )\n }\n onClick={handleClick}\n label={copied ? 'Copied to clipboard' : 'Copy message'}\n className={className}\n />\n );\n}\n\nAIMessageCopyButton.displayName = 'AIMessage.CopyButton';\n\n// =============================================================================\n// AIMessage.ListButton - List/expand button\n// =============================================================================\n\nexport interface AIMessageListButtonProps {\n /** Click handler */\n onClick?: () => void;\n /** Additional class name */\n className?: string;\n}\n\nfunction AIMessageListButton({ onClick, className }: AIMessageListButtonProps) {\n return (\n <ReactionButton\n icon={\n <List className=\"size-4 text-secondary-foreground\" aria-hidden=\"true\" />\n }\n onClick={onClick}\n label=\"Show list\"\n className={className}\n />\n );\n}\n\nAIMessageListButton.displayName = 'AIMessage.ListButton';\n\n// =============================================================================\n// AIMessage.Actions - Action toolbar container\n// =============================================================================\n\nexport interface AIMessageActionsProps {\n /** Children (action buttons) */\n children?: React.ReactNode;\n /** Additional class name */\n className?: string;\n}\n\nfunction AIMessageActions({ children, className }: AIMessageActionsProps) {\n const ctx = React.useContext(AIMessageContext);\n\n return (\n <div\n data-slot=\"ai-message-actions\"\n role=\"toolbar\"\n aria-label=\"Message actions\"\n className={cn(\n 'flex items-center gap-0.5 rounded-full overflow-hidden',\n className,\n )}\n >\n {children ??\n (ctx && (\n <>\n <AIMessageThumbsUp\n onClick={ctx.onThumbsUp}\n active={ctx.thumbsUpActive}\n />\n <AIMessageThumbsDown\n onClick={ctx.onThumbsDown}\n active={ctx.thumbsDownActive}\n />\n <AIMessageCopyButton onClick={ctx.onCopy} />\n <AIMessageListButton onClick={ctx.onShowList} />\n </>\n ))}\n </div>\n );\n}\n\nAIMessageActions.displayName = 'AIMessage.Actions';\n\n// =============================================================================\n// AIMessage.TypingIndicator - Bouncing dots\n// =============================================================================\n\nexport interface AIMessageTypingIndicatorProps {\n /** Additional class name */\n className?: string;\n}\n\nfunction AIMessageTypingIndicator({\n className,\n}: AIMessageTypingIndicatorProps) {\n return (\n <div\n data-slot=\"ai-message-typing-indicator\"\n className={cn(\n 'flex items-center gap-1 motion-reduce:animate-none',\n className,\n )}\n >\n <AITypingIndicator size=\"sm\" color=\"var(--muted-foreground)\" />\n </div>\n );\n}\n\nAIMessageTypingIndicator.displayName = 'AIMessage.TypingIndicator';\n\n// =============================================================================\n// Attachment Types\n// =============================================================================\n\nexport interface Attachment {\n id: string;\n name: string;\n size: string;\n /** File extension (e.g., 'pdf', 'jpg', 'doc') */\n extension?: string;\n url?: string;\n thumbnailUrl?: string;\n}\n\n// =============================================================================\n// AIMessage.AttachmentPreview - Single attachment preview\n// =============================================================================\n\nexport interface AIMessageAttachmentPreviewProps {\n /** Attachment data */\n attachment: Attachment;\n /** Message type for styling */\n messageType?: 'received' | 'sent';\n /** Click handler */\n onClick?: () => void;\n /** Additional class name */\n className?: string;\n}\n\nfunction AIMessageAttachmentPreview({\n attachment,\n messageType = 'received',\n onClick,\n className,\n}: AIMessageAttachmentPreviewProps) {\n // Derive extension from attachment.extension or extract from filename\n const getExtension = () => {\n if (attachment.extension) {\n return attachment.extension;\n }\n const parts = attachment.name.split('.');\n if (parts.length > 1) {\n return parts[parts.length - 1];\n }\n return '';\n };\n\n const extension = getExtension();\n\n const bubbleClasses =\n messageType === 'sent'\n ? 'bg-primary/10 border border-primary-foreground/20 rounded-2xl'\n : 'bg-muted rounded-2xl';\n\n return (\n <button\n type=\"button\"\n data-slot=\"ai-message-attachment-preview\"\n onClick={onClick}\n aria-label={`Attachment: ${attachment.name}, ${attachment.size}`}\n className={cn(\n 'flex items-center gap-3 p-3 min-h-11 hover:bg-accent transition-colors w-full max-w-[320px] focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-ring',\n bubbleClasses,\n className,\n )}\n >\n {attachment.thumbnailUrl ? (\n <img\n src={attachment.thumbnailUrl}\n alt={attachment.name}\n className=\"size-10 rounded-md object-cover\"\n />\n ) : (\n <FileTypeIcon extension={extension} size=\"md\" className=\"shrink-0\" />\n )}\n <div className=\"flex flex-col items-start min-w-0\">\n <span className=\"text-sm font-medium text-secondary-foreground truncate w-full\">\n {attachment.name}\n </span>\n <span className=\"text-sm text-muted-foreground\">{attachment.size}</span>\n </div>\n </button>\n );\n}\n\nAIMessageAttachmentPreview.displayName = 'AIMessage.AttachmentPreview';\n\n// =============================================================================\n// AIMessage.Attachments - Attachments container\n// =============================================================================\n\nexport interface AIMessageAttachmentsProps {\n /** Attachments to display */\n attachments: Attachment[];\n /** Message type for styling */\n messageType?: 'received' | 'sent';\n /** Callback when attachment is clicked */\n onAttachmentClick?: (attachment: Attachment) => void;\n /** Additional class name */\n className?: string;\n}\n\nfunction AIMessageAttachments({\n attachments,\n messageType = 'received',\n onAttachmentClick,\n className,\n}: AIMessageAttachmentsProps) {\n if (!attachments?.length) return null;\n\n return (\n <div\n data-slot=\"ai-message-attachments\"\n className={cn('flex flex-col gap-2 mt-1', className)}\n >\n {attachments.map((attachment) => (\n <AIMessageAttachmentPreview\n key={attachment.id}\n attachment={attachment}\n messageType={messageType}\n onClick={() => onAttachmentClick?.(attachment)}\n />\n ))}\n </div>\n );\n}\n\nAIMessageAttachments.displayName = 'AIMessage.Attachments';\n\n// =============================================================================\n// AIMessage.Avatar - Avatar with agent indicator\n// =============================================================================\n\nexport interface AIMessageAvatarProps extends AvatarProps {\n /** Whether sender is an agent */\n isAgent?: boolean;\n}\n\nfunction AIMessageAvatar({ isAgent, ...props }: AIMessageAvatarProps) {\n return (\n <Avatar\n data-slot=\"ai-message-avatar\"\n {...props}\n size=\"md\"\n indicator={isAgent ? 'verified' : props.indicator}\n />\n );\n}\n\nAIMessageAvatar.displayName = 'AIMessage.Avatar';\n\n// =============================================================================\n// AIMessage.Content - Message content with markdown support\n// =============================================================================\n\nexport interface AIMessageContentProps {\n /** Message content */\n children?: React.ReactNode;\n /** Content as string (alternative to children) */\n content?: string;\n /** Whether to render content as markdown. Defaults to true for received, false for sent. */\n markdown?: boolean;\n /** Callback for interactive component events */\n onInteraction?: (event: AIInteractionEvent) => void;\n /** Additional class name */\n className?: string;\n}\n\nfunction AIMessageContent({\n children,\n content,\n markdown,\n onInteraction,\n className,\n}: AIMessageContentProps) {\n const ctx = React.useContext(AIMessageContext);\n const type = ctx?.type ?? 'received';\n const isSent = type === 'sent';\n\n const shouldRenderMarkdown = markdown ?? type === 'received';\n const textContent = content ?? (typeof children === 'string' ? children : '');\n const variant = isSent ? 'inverted' : 'default';\n\n return (\n <div\n data-slot=\"ai-message-content\"\n className={cn('w-full', messageOverflowWrapClasses, className)}\n >\n {shouldRenderMarkdown && textContent ? (\n <AIInteractionProvider onInteraction={onInteraction}>\n <MarkdownRenderer\n variant={variant}\n className={cn(\n 'text-base',\n isSent ? 'text-primary-foreground' : 'text-foreground',\n )}\n >\n {textContent}\n </MarkdownRenderer>\n </AIInteractionProvider>\n ) : textContent ? (\n <p\n className={cn(\n 'text-sm leading-5 whitespace-pre-wrap',\n messageOverflowWrapClasses,\n isSent ? 'text-primary-foreground' : 'text-foreground',\n )}\n >\n {textContent}\n </p>\n ) : (\n children\n )}\n </div>\n );\n}\n\nAIMessageContent.displayName = 'AIMessage.Content';\n\n// =============================================================================\n// AIMessage.Header - Header with name and timestamp\n// =============================================================================\n\nexport interface AIMessageHeaderProps {\n /** Sender name */\n senderName?: string;\n /** Timestamp string */\n timestamp?: string;\n /** Show avatar slot */\n avatar?: React.ReactNode;\n /** Additional class name */\n className?: string;\n}\n\nfunction AIMessageHeader({\n senderName,\n timestamp,\n avatar,\n className,\n}: AIMessageHeaderProps) {\n const ctx = React.useContext(AIMessageContext);\n const isSent = ctx?.type === 'sent';\n const compact = ctx?.compact ?? false;\n\n if (compact) return null;\n\n return (\n <div\n data-slot=\"ai-message-header\"\n className={cn('flex items-center justify-between w-full', className)}\n >\n <div className=\"flex items-center gap-2 min-w-0 flex-1\">\n {avatar && <div className=\"shrink-0\">{avatar}</div>}\n <span\n className={cn(\n 'text-sm font-medium truncate',\n isSent ? 'text-primary-foreground' : 'text-secondary-foreground',\n )}\n >\n {isSent ? (senderName ?? 'You') : senderName}\n </span>\n </div>\n {timestamp && (\n <span\n className={cn(\n 'text-xs shrink-0',\n isSent ? 'text-primary-foreground/90' : 'text-muted-foreground',\n )}\n >\n {timestamp}\n </span>\n )}\n </div>\n );\n}\n\nAIMessageHeader.displayName = 'AIMessage.Header';\n\n// =============================================================================\n// AIMessage.Root - Root container for composable API\n// =============================================================================\n\nexport interface AIMessageRootProps\n extends Omit<HTMLAttributes<HTMLDivElement>, 'content'> {\n /** Message type */\n type?: 'received' | 'sent';\n /** Whether sender is an AI agent */\n isAgent?: boolean;\n /** Whether in compact mode */\n compact?: boolean;\n /** Whether AI is typing */\n isTyping?: boolean;\n /** Callback when thumbs up is clicked */\n onThumbsUp?: () => void;\n /** Callback when thumbs down is clicked */\n onThumbsDown?: () => void;\n /** Callback when copy is clicked */\n onCopy?: () => void;\n /** Callback when list/expand is clicked */\n onShowList?: () => void;\n /** Whether thumbs up is active */\n thumbsUpActive?: boolean;\n /** Whether thumbs down is active */\n thumbsDownActive?: boolean;\n /** Children */\n children?: React.ReactNode;\n /** Additional class name */\n className?: string;\n}\n\nconst AIMessageRoot = forwardRef<HTMLDivElement, AIMessageRootProps>(\n (\n {\n type = 'received',\n isAgent = false,\n compact = false,\n isTyping = false,\n onThumbsUp,\n onThumbsDown,\n onCopy,\n onShowList,\n thumbsUpActive,\n thumbsDownActive,\n children,\n className,\n ...props\n },\n ref,\n ) => {\n const isSent = type === 'sent';\n\n const contextValue = React.useMemo<AIMessageContextValue>(\n () => ({\n type,\n isAgent,\n compact,\n isTyping,\n onThumbsUp,\n onThumbsDown,\n onCopy,\n onShowList,\n thumbsUpActive,\n thumbsDownActive,\n }),\n [\n type,\n isAgent,\n compact,\n isTyping,\n onThumbsUp,\n onThumbsDown,\n onCopy,\n onShowList,\n thumbsUpActive,\n thumbsDownActive,\n ],\n );\n\n return (\n <AIMessageContext.Provider value={contextValue}>\n <div\n ref={ref}\n data-slot=\"ai-message\"\n className={cn(\n messageVariants({ type }),\n isSent ? 'pe-2' : 'ps-0',\n isSent ? 'delight-slide-in-end' : 'delight-slide-up',\n className,\n )}\n {...props}\n >\n <div\n className={cn(\n 'flex min-w-0 max-w-full flex-col gap-1.5 items-start',\n isSent && 'items-end',\n )}\n >\n {children}\n </div>\n </div>\n </AIMessageContext.Provider>\n );\n },\n);\n\nAIMessageRoot.displayName = 'AIMessage.Root';\n\n// =============================================================================\n// Main AIMessage Component (Monolithic API)\n// =============================================================================\n\nexport interface AIMessageProps\n extends VariantProps<typeof messageVariants>,\n Omit<HTMLAttributes<HTMLDivElement>, 'content'> {\n /** Message type - 'received' for incoming, 'sent' for outgoing messages */\n type?: 'received' | 'sent';\n /** Message content */\n content?: string;\n /** Sender name */\n senderName?: string;\n /** Timestamp */\n timestamp?: string;\n /** Avatar — pass AvatarProps object or a React element */\n avatar?: AvatarProps | React.ReactElement;\n /** Whether the sender is an AI agent */\n isAgent?: boolean;\n /** Whether message is in compact mode (no avatar on subsequent messages) */\n compact?: boolean;\n /** Whether the AI is currently typing */\n isTyping?: boolean;\n /** Whether to render content as markdown. Defaults to true for received, false for sent. */\n markdown?: boolean;\n /** Callback when an interactive component triggers an interaction */\n onInteraction?: (event: AIInteractionEvent) => void;\n /** Attachments */\n attachments?: Attachment[];\n /** Emoji reactions */\n reactions?: EmojiReaction[];\n /** Whether to show action toolbar (for agent messages) */\n showActions?: boolean;\n /** Callback when thumbs up is clicked */\n onThumbsUp?: () => void;\n /** Callback when thumbs down is clicked */\n onThumbsDown?: () => void;\n /** Callback when copy is clicked */\n onCopy?: () => void;\n /** Callback when list/expand is clicked */\n onShowList?: () => void;\n /** Callback when emoji reaction is clicked */\n onReactionClick?: (emoji: string) => void;\n /** Callback when attachment is clicked */\n onAttachmentClick?: (attachment: Attachment) => void;\n /** Whether thumbs up is active */\n thumbsUpActive?: boolean;\n /** Whether thumbs down is active */\n thumbsDownActive?: boolean;\n /** Additional class name */\n className?: string;\n}\n\nconst AIMessageDefault = forwardRef<HTMLDivElement, AIMessageProps>(\n (\n {\n type = 'received',\n content,\n senderName,\n timestamp,\n avatar,\n isAgent = false,\n compact = false,\n isTyping = false,\n markdown,\n onInteraction,\n attachments,\n reactions,\n showActions = false,\n onThumbsUp,\n onThumbsDown,\n onCopy,\n onShowList,\n onReactionClick,\n onAttachmentClick,\n thumbsUpActive,\n thumbsDownActive,\n className,\n ...props\n },\n ref,\n ) => {\n return (\n <AIMessageRoot\n ref={ref}\n type={type}\n isAgent={isAgent}\n compact={compact}\n isTyping={isTyping}\n onThumbsUp={onThumbsUp}\n onThumbsDown={onThumbsDown}\n onCopy={onCopy}\n onShowList={onShowList}\n thumbsUpActive={thumbsUpActive}\n thumbsDownActive={thumbsDownActive}\n className={className}\n {...props}\n >\n {type !== 'sent' &&\n !compact &&\n avatar &&\n (React.isValidElement(avatar) ? (\n avatar\n ) : (\n <AIMessageAvatar {...(avatar as AvatarProps)} isAgent={isAgent} />\n ))}\n\n <AIMessageBubble>\n {(type !== 'sent' || senderName || timestamp) && (\n <AIMessageHeader senderName={senderName} timestamp={timestamp} />\n )}\n\n {isTyping ? (\n <AIMessageTypingIndicator />\n ) : (\n content && (\n <AIMessageContent\n content={content}\n markdown={markdown}\n onInteraction={onInteraction}\n />\n )\n )}\n </AIMessageBubble>\n\n {!isTyping && attachments && attachments.length > 0 && (\n <AIMessageAttachments\n attachments={attachments}\n messageType={type ?? 'received'}\n onAttachmentClick={onAttachmentClick}\n />\n )}\n\n {!isTyping && (showActions || reactions?.length) && (\n <div className=\"flex items-center gap-1\">\n {showActions && isAgent && <AIMessageActions />}\n {reactions && reactions.length > 0 && (\n <AIMessageReactions\n reactions={reactions}\n onReactionClick={onReactionClick}\n />\n )}\n </div>\n )}\n </AIMessageRoot>\n );\n },\n);\n\nAIMessageDefault.displayName = 'AIMessage';\n\n// =============================================================================\n// Compound Component (Dual-API via Object.assign)\n// =============================================================================\n\n/**\n * AIMessage - Dual-API component for AI chat messages.\n *\n * Supports two usage patterns:\n *\n * 1. **Monolithic API (batteries-included)**:\n * ```tsx\n * <AIMessage\n * content=\"Hello!\"\n * senderName=\"Assistant\"\n * avatar={{ src: '...' }}\n * isAgent\n * showActions\n * />\n * ```\n *\n * 2. **Composable API (full customization)**:\n * ```tsx\n * <AIMessage.Root type=\"received\" isAgent>\n * <AIMessage.Avatar src=\"...\" isAgent />\n * <AIMessage.Bubble>\n * <AIMessage.Header senderName=\"Assistant\" timestamp=\"Now\" />\n * <AIMessage.Content markdown>\n * Hello!\n * </AIMessage.Content>\n * </AIMessage.Bubble>\n * <AIMessage.Actions>\n * <AIMessage.ThumbsUp onClick={...} />\n * <AIMessage.ThumbsDown onClick={...} />\n * <AIMessage.CopyButton onClick={...} />\n * </AIMessage.Actions>\n * </AIMessage.Root>\n * ```\n */\nconst AIMessage = Object.assign(AIMessageDefault, {\n Root: AIMessageRoot,\n Bubble: AIMessageBubble,\n Header: AIMessageHeader,\n Avatar: AIMessageAvatar,\n Content: AIMessageContent,\n Actions: AIMessageActions,\n Reactions: AIMessageReactions,\n Attachments: AIMessageAttachments,\n AttachmentPreview: AIMessageAttachmentPreview,\n TypingIndicator: AIMessageTypingIndicator,\n CopyButton: AIMessageCopyButton,\n ThumbsUp: AIMessageThumbsUp,\n ThumbsDown: AIMessageThumbsDown,\n ListButton: AIMessageListButton,\n});\n\n// =============================================================================\n// Named Exports\n// =============================================================================\n\n// Type exports\nexport type { AIMessageRootProps as AIMessageComposableProps };\nexport {\n AIMessage,\n AIMessageActions,\n AIMessageAttachmentPreview,\n AIMessageAttachments,\n AIMessageAvatar,\n AIMessageBubble,\n AIMessageContent,\n AIMessageCopyButton,\n AIMessageHeader,\n AIMessageListButton,\n AIMessageReactions,\n // Composable subcomponents\n AIMessageRoot,\n AIMessageThumbsDown,\n AIMessageThumbsUp,\n AIMessageTypingIndicator,\n // Variants\n messageBubbleVariants,\n messageVariants,\n // Context hook for custom subcomponents\n useAIMessageContext,\n};\n"],"mappings":"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"}
|