@json-to-office/jto 6.8.0 → 7.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/dist/cli.js +17 -9
  2. package/dist/cli.js.map +1 -1
  3. package/dist/client/assets/{HomePage-DdKO7Rz8.js → HomePage-CAQsE0sn.js} +4 -4
  4. package/dist/client/assets/HomePage-CAQsE0sn.js.map +1 -0
  5. package/dist/client/assets/{JsonEditorPage-CIB7kfUW.js → JsonEditorPage-Cqz2zDan.js} +3 -3
  6. package/dist/client/assets/{JsonEditorPage-CIB7kfUW.js.map → JsonEditorPage-Cqz2zDan.js.map} +1 -1
  7. package/dist/client/assets/{MonacoPluginProvider-Cql9aylS.js → MonacoPluginProvider-FJHgHgFQ.js} +5 -5
  8. package/dist/client/assets/{MonacoPluginProvider-Cql9aylS.js.map → MonacoPluginProvider-FJHgHgFQ.js.map} +1 -1
  9. package/dist/client/assets/{_virtual_jto-plugin-type-libs-BJgH7I8Z.js → _virtual_jto-plugin-type-libs-DroopP3q.js} +39 -14
  10. package/dist/client/assets/{_virtual_jto-plugin-type-libs-BJgH7I8Z.js.map → _virtual_jto-plugin-type-libs-DroopP3q.js.map} +1 -1
  11. package/dist/client/assets/_virtual_jto-sandbox-runtime-v4kQF3ee.js +2 -0
  12. package/dist/client/assets/_virtual_jto-sandbox-runtime-v4kQF3ee.js.map +1 -0
  13. package/dist/client/assets/{editor-Dl0mPZWB.js → editor-1mTGQjga.js} +2 -2
  14. package/dist/client/assets/{editor-Dl0mPZWB.js.map → editor-1mTGQjga.js.map} +1 -1
  15. package/dist/client/assets/{editor-monaco-json-BWLlWM6o.js → editor-monaco-json-B19wOO_b.js} +2 -2
  16. package/dist/client/assets/{editor-monaco-json-BWLlWM6o.js.map → editor-monaco-json-B19wOO_b.js.map} +1 -1
  17. package/dist/client/assets/{index-Db2WFiF0.js → index-Da5mi8tP.js} +2 -2
  18. package/dist/client/assets/{index-Db2WFiF0.js.map → index-Da5mi8tP.js.map} +1 -1
  19. package/dist/client/assets/{index-1Vg-Jg2R.js → index-DsuZTLjf.js} +5 -5
  20. package/dist/client/assets/index-DsuZTLjf.js.map +1 -0
  21. package/dist/client/assets/{preview-BXysnPth.js → preview-T1T-uQbx.js} +2 -2
  22. package/dist/client/assets/preview-T1T-uQbx.js.map +1 -0
  23. package/dist/client/assets/{useQualityAnalysis-Dr3UHxyN.js → useQualityAnalysis-CnLgG345.js} +2 -2
  24. package/dist/client/assets/{useQualityAnalysis-Dr3UHxyN.js.map → useQualityAnalysis-CnLgG345.js.map} +1 -1
  25. package/dist/client/index.html +1 -1
  26. package/dist/client/templates/client-report-blocks.docx.json +1 -1
  27. package/dist/client/templates/consulting-deck-blocks.pptx.json +39 -18
  28. package/dist/client/templates/data-report-presentation.pptx.json +1 -1
  29. package/dist/client/templates/management-plan.pptx.json +4 -4
  30. package/dist/client/templates/minimalist-pitch-deck.pptx.json +1 -1
  31. package/dist/client/templates/modern-annual-report-3.docx.json +1 -0
  32. package/dist/client/templates/technical-report-blocks.docx.json +1 -1
  33. package/package.json +8 -8
  34. package/dist/client/assets/HomePage-DdKO7Rz8.js.map +0 -1
  35. package/dist/client/assets/_virtual_jto-sandbox-runtime-BFXK15tx.js +0 -2
  36. package/dist/client/assets/_virtual_jto-sandbox-runtime-BFXK15tx.js.map +0 -1
  37. package/dist/client/assets/index-1Vg-Jg2R.js.map +0 -1
  38. package/dist/client/assets/preview-BXysnPth.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"preview-BXysnPth.js","sources":["../../../src/client/components/ui/loading-states.tsx","../../../src/client/components/playground/preview-frame.tsx","../../../src/client/components/playground/warnings-panel.tsx","../../../src/client/components/playground/quality-policy-editor.tsx","../../../src/client/components/playground/quality-controls.tsx","../../../src/client/lib/json-pointer.ts","../../../src/client/lib/quality-fixes.ts","../../../src/client/components/playground/quality-panel.tsx","../../../src/client/components/playground/unavailable-theme-warning.tsx","../../../src/client/components/theme-editor/theme-specimen.tsx","../../../src/client/components/playground/theme-sample-panel.tsx","../../../src/client/lib/render.ts","../../../src/client/hooks/useApplyQualityFix.ts","../../../src/client/components/ui/progress.tsx","../../../src/client/components/cache-metrics.tsx","../../../src/client/components/playground/preview.tsx"],"sourcesContent":["import { useEffect, useMemo, useState } from 'react';\nimport { cn } from '@/lib/utils';\nimport { Spinner } from './spinner';\nimport { Skeleton } from './skeleton';\nimport { Button } from './button';\n\ninterface LoadingOverlayProps {\n isLoading: boolean;\n children: React.ReactNode;\n message?: string;\n className?: string;\n}\n\nexport function LoadingOverlay({\n isLoading,\n children,\n message = 'Loading...',\n className,\n}: LoadingOverlayProps) {\n return (\n <div className={cn('relative', className)}>\n {children}\n {isLoading && (\n <div className=\"absolute inset-0 bg-background/80 backdrop-blur-sm flex items-center justify-center z-50\">\n <div className=\"flex flex-col items-center gap-2\">\n <Spinner size=\"lg\" />\n <p className=\"text-sm text-muted-foreground\">{message}</p>\n </div>\n </div>\n )}\n </div>\n );\n}\n\ninterface DocumentGenerationLoaderProps {\n className?: string;\n currentStage?: 'parsing' | 'building' | 'rendering' | 'finalizing';\n message?: string;\n /** Source JSON of the document being built — drives the content summary. */\n documentText?: string;\n /** Date.now() when the build started — drives the elapsed timer. */\n startedAt?: number;\n /** When provided, renders a Cancel button that aborts the build. */\n onCancel?: () => void;\n}\n\n/** Ticks every 100ms and returns whole elapsed seconds since `startedAt`. */\nfunction useElapsedSeconds(startedAt?: number): number {\n // Freeze the fallback start on first render so a caller that never passes\n // `startedAt` still gets a stable timer instead of one reset per render.\n const [fallbackStart] = useState(() => Date.now());\n const start = startedAt ?? fallbackStart;\n const [now, setNow] = useState(() => Date.now());\n useEffect(() => {\n const id = setInterval(() => setNow(Date.now()), 100);\n return () => clearInterval(id);\n }, []);\n return Math.max(0, (now - start) / 1000);\n}\n\ninterface DocumentSummary {\n title?: string;\n counts: { label: string; count: number }[];\n visualCount: number;\n imageCount: number;\n}\n\n/**\n * Walk a JTO document tree and count the component types worth narrating.\n * Best-effort: any parse/shape surprise returns null and the loader simply\n * omits the summary row.\n */\nfunction summarizeDocument(text?: string): DocumentSummary | null {\n if (!text) return null;\n try {\n const root = JSON.parse(text);\n if (!root || typeof root !== 'object') return null;\n const counts = new Map<string, number>();\n const stack: unknown[] = [root];\n while (stack.length > 0) {\n const node = stack.pop();\n if (!node || typeof node !== 'object') continue;\n const { name, children } = node as {\n name?: unknown;\n children?: unknown;\n };\n if (typeof name === 'string') {\n counts.set(name, (counts.get(name) ?? 0) + 1);\n }\n if (Array.isArray(children)) stack.push(...children);\n }\n // Ordered by how much each type usually tells the user about build cost.\n const interesting: [key: string, singular: string, plural: string][] = [\n ['slide', 'slide', 'slides'],\n ['section', 'section', 'sections'],\n ['visual', 'visual', 'visuals'],\n ['chart', 'chart', 'charts'],\n ['image', 'image', 'images'],\n ['table', 'table', 'tables'],\n ['shape', 'shape', 'shapes'],\n ['paragraph', 'paragraph', 'paragraphs'],\n ];\n const summary = interesting\n .map(([key, singular, plural]) => {\n const count = counts.get(key) ?? 0;\n return { label: count === 1 ? singular : plural, count };\n })\n .filter((entry) => entry.count > 0)\n .slice(0, 5);\n const title = (root as { props?: { metadata?: { title?: unknown } } }).props\n ?.metadata?.title;\n return {\n title: typeof title === 'string' ? title : undefined,\n counts: summary,\n visualCount: (counts.get('visual') ?? 0) + (counts.get('chart') ?? 0),\n imageCount: counts.get('image') ?? 0,\n };\n } catch {\n return null;\n }\n}\n\n/** Rotating context lines shown once a build takes more than a moment. */\nfunction buildHints(summary: DocumentSummary | null): string[] {\n const hints: string[] = [];\n if (summary && summary.visualCount > 0) {\n hints.push(\n `${summary.visualCount} visual${summary.visualCount === 1 ? '' : 's'} in this document ${\n summary.visualCount === 1 ? 'is' : 'are'\n } rasterized on first build — later builds reuse the cached renders.`\n );\n }\n if (summary && summary.imageCount > 3) {\n hints.push(\n 'Large embedded images dominate build time — downscaling them speeds up iteration.'\n );\n }\n hints.push(\n 'Re-running an unchanged document is served from the cache almost instantly.',\n 'Generation warnings, if any, will appear above the preview when the build completes.'\n );\n return hints;\n}\n\nconst CheckIcon = () => (\n <svg\n className=\"h-3.5 w-3.5 text-success\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M3 8.5L6.5 12L13 4.5\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n);\n\nexport function DocumentGenerationLoader({\n className,\n currentStage = 'parsing',\n message,\n documentText,\n startedAt,\n onCancel,\n}: DocumentGenerationLoaderProps) {\n const stages = ['parsing', 'building', 'rendering', 'finalizing'] as const;\n const stageLabels: Record<(typeof stages)[number], string> = {\n parsing: 'Validating JSON',\n building: 'Building structure',\n rendering: 'Rendering content',\n finalizing: 'Finalizing document',\n };\n\n const currentStageIndex = stages.indexOf(currentStage);\n const elapsed = useElapsedSeconds(startedAt);\n const summary = useMemo(\n () => summarizeDocument(documentText),\n [documentText]\n );\n const hints = useMemo(() => buildHints(summary), [summary]);\n // Hints appear only for builds long enough to leave the user wondering,\n // then rotate so a long rasterization pass keeps saying something new.\n const showHints = elapsed > 3;\n const hintIndex = Math.floor(Math.max(0, elapsed - 3) / 5) % hints.length;\n\n return (\n <div className={cn('p-6 max-w-lg mx-auto space-y-5', className)}>\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"flex items-center gap-3 min-w-0\">\n <Spinner size=\"md\" />\n <div className=\"space-y-0.5 min-w-0\">\n <p className=\"text-sm font-medium truncate\">\n {summary?.title\n ? `Generating “${summary.title}”`\n : 'Generating document'}\n </p>\n {/* The live region covers only the stage message — putting it on\n the container would re-announce the whole loader every 100ms\n elapsed-timer tick. */}\n <p\n className=\"text-xs text-muted-foreground truncate\"\n role=\"status\"\n aria-live=\"polite\"\n >\n {message || `${stageLabels[currentStage]}...`}\n </p>\n </div>\n </div>\n <span\n className=\"shrink-0 rounded-full bg-secondary px-2 py-0.5 text-xs text-muted-foreground tabular-nums\"\n aria-hidden=\"true\"\n >\n {elapsed.toFixed(1)}s\n </span>\n </div>\n\n {summary && summary.counts.length > 0 && (\n <div className=\"flex flex-wrap gap-1.5\" aria-label=\"Document contents\">\n {summary.counts.map(({ label, count }) => (\n <span\n key={label}\n className=\"inline-flex items-center gap-1 rounded-full border px-2 py-0.5 text-xs text-muted-foreground\"\n >\n <span className=\"font-medium text-foreground tabular-nums\">\n {count}\n </span>\n {label}\n </span>\n ))}\n </div>\n )}\n\n <div className=\"space-y-3\">\n {stages.map((stage, index) => {\n const isActive = index === currentStageIndex;\n const isCompleted = index < currentStageIndex;\n return (\n <div key={stage} className=\"space-y-1.5\">\n <div className=\"flex items-center justify-between text-xs\">\n <span\n className={cn(\n isActive\n ? 'text-primary font-medium'\n : isCompleted\n ? 'text-muted-foreground'\n : 'text-muted-foreground/60'\n )}\n >\n {stageLabels[stage]}\n </span>\n {isCompleted ? (\n <CheckIcon />\n ) : isActive ? (\n <Spinner size=\"sm\" className=\"h-3.5 w-3.5\" />\n ) : (\n <span className=\"h-3.5 w-3.5 rounded-full border border-muted-foreground/40\" />\n )}\n </div>\n <div className=\"w-full bg-secondary rounded-full h-1.5 overflow-hidden\">\n {isCompleted ? (\n <div className=\"h-full w-full rounded-full bg-success\" />\n ) : isActive ? (\n // Honest indeterminate sweep — we have no real progress\n // signal within a stage, so don't fake a full bar.\n <div className=\"h-full w-2/5 rounded-full bg-primary animate-progress-indeterminate\" />\n ) : null}\n </div>\n </div>\n );\n })}\n </div>\n\n <div className=\"flex items-center justify-between gap-3 min-h-8\">\n <p\n className={cn(\n 'text-xs text-muted-foreground/80 italic transition-opacity duration-500',\n showHints ? 'opacity-100' : 'opacity-0'\n )}\n >\n {hints[hintIndex]}\n </p>\n {onCancel && (\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={onCancel}\n className=\"shrink-0\"\n >\n Cancel\n </Button>\n )}\n </div>\n </div>\n );\n}\n\ninterface GenerationOverlayProps {\n mode: 'generating' | 'rendering';\n message?: string;\n startedAt?: number;\n onCancel?: () => void;\n className?: string;\n}\n\n/**\n * Compact card for the overlay shown on top of an existing preview while a\n * rebuild or re-render is in flight.\n */\nexport function GenerationOverlay({\n mode,\n message,\n startedAt,\n onCancel,\n className,\n}: GenerationOverlayProps) {\n const elapsed = useElapsedSeconds(startedAt);\n return (\n <div\n className={cn(\n 'flex flex-col items-center gap-2 rounded-md border bg-background/95 px-6 py-4 shadow-sm',\n className\n )}\n >\n <div className=\"flex items-center gap-2\">\n <Spinner size=\"md\" />\n {/* Live region on the label only — the elapsed badge ticks every\n 100ms and must not retrigger screen-reader announcements. */}\n <p className=\"text-sm font-medium\" role=\"status\" aria-live=\"polite\">\n {mode === 'generating' ? 'Generating' : 'Rendering'}\n </p>\n <span\n className=\"rounded-full bg-secondary px-2 py-0.5 text-xs text-muted-foreground tabular-nums\"\n aria-hidden=\"true\"\n >\n {elapsed.toFixed(1)}s\n </span>\n </div>\n {message && (\n <p className=\"max-w-xs text-center text-xs text-muted-foreground truncate\">\n {message}\n </p>\n )}\n {mode === 'generating' && onCancel && (\n <Button variant=\"outline\" size=\"sm\" onClick={onCancel}>\n Cancel\n </Button>\n )}\n </div>\n );\n}\n\ninterface PreviewLoadingProps {\n renderingLibrary?: string;\n className?: string;\n}\n\nexport function PreviewLoading({\n renderingLibrary,\n className,\n}: PreviewLoadingProps) {\n const getLibraryInfo = (library?: string) => {\n switch (library) {\n case 'LibreOffice':\n return {\n name: 'LibreOffice',\n description: 'Converting document to PDF locally...',\n };\n case 'Office':\n return {\n name: 'Microsoft Office',\n description: 'Uploading file and loading Office viewer...',\n };\n case 'Docs':\n return {\n name: 'Google Docs',\n description: 'Uploading file and loading Docs viewer...',\n };\n default:\n return { name: 'Default', description: 'Processing document...' };\n }\n };\n\n const { name, description } = getLibraryInfo(renderingLibrary);\n\n return (\n <div\n className={cn(\n 'flex flex-col items-center justify-center h-full p-8 space-y-4',\n className\n )}\n >\n <Spinner size=\"lg\" />\n <div className=\"text-center space-y-2\">\n <p className=\"text-sm font-medium\">Rendering Preview</p>\n <p className=\"text-xs text-muted-foreground\">Using {name} renderer</p>\n <p className=\"text-xs text-muted-foreground/80\">{description}</p>\n </div>\n\n <div className=\"w-full max-w-md space-y-3\">\n <Skeleton className=\"h-16 w-full\" />\n <div className=\"space-y-2\">\n <Skeleton className=\"h-4 w-full\" />\n <Skeleton className=\"h-4 w-3/4\" />\n <Skeleton className=\"h-4 w-1/2\" />\n </div>\n <Skeleton className=\"h-12 w-full\" />\n </div>\n </div>\n );\n}\n\ninterface InlineLoaderProps {\n message?: string;\n size?: 'sm' | 'md';\n className?: string;\n}\n\nexport function InlineLoader({\n message = 'Loading...',\n size = 'sm',\n className,\n}: InlineLoaderProps) {\n return (\n <div className={cn('flex items-center gap-2', className)}>\n <Spinner size={size} />\n <span className=\"text-sm text-muted-foreground\">{message}</span>\n </div>\n );\n}\n\ninterface FileOperationLoaderProps {\n operation: 'upload' | 'download' | 'save' | 'delete';\n fileName?: string;\n progress?: number;\n className?: string;\n}\n\nexport function FileOperationLoader({\n operation,\n fileName,\n progress,\n className,\n}: FileOperationLoaderProps) {\n const operationLabels = {\n upload: 'Uploading',\n download: 'Downloading',\n save: 'Saving',\n delete: 'Deleting',\n };\n\n return (\n <div\n className={cn(\n 'flex items-center gap-3 p-3 border rounded-sm bg-header-bg',\n className\n )}\n >\n <Spinner size=\"sm\" />\n <div className=\"flex-1 min-w-0\">\n <p className=\"text-sm font-medium truncate\">\n {operationLabels[operation]} {fileName && `\"${fileName}\"`}\n </p>\n {progress !== undefined && (\n <div className=\"mt-1\">\n <div className=\"flex justify-between text-xs mb-1\">\n <span>{progress}%</span>\n <span className=\"text-muted-foreground\">\n {progress < 100 ? 'In progress...' : 'Complete'}\n </span>\n </div>\n <div className=\"w-full bg-secondary rounded-full h-1.5\">\n <div\n className=\"bg-primary h-1.5 rounded-full transition-all duration-300\"\n style={{ width: `${progress}%` }}\n />\n </div>\n </div>\n )}\n </div>\n </div>\n );\n}\n","import React, { useEffect, useState } from 'react';\nimport {\n DocumentGenerationLoader,\n GenerationOverlay,\n PreviewLoading,\n} from '../ui/loading-states';\nimport { FORMAT_LABEL } from '../../lib/env';\n\nconst PreviewFrame = React.forwardRef<\n HTMLIFrameElement,\n {\n isLoading: boolean;\n iframeSrc?: string;\n iframeSrcDoc?: string;\n isGenerating?: boolean;\n generationProgress?: {\n stage: 'parsing' | 'building' | 'rendering' | 'finalizing';\n message?: string;\n };\n /** Source JSON being built — feeds the loader's content summary. */\n generationDocumentText?: string;\n /** Date.now() when the build started — feeds the elapsed timer. */\n generationStartedAt?: number;\n /** Aborts the in-flight build; renders a Cancel button when present. */\n onCancelGeneration?: () => void;\n }\n>(\n (\n {\n isLoading,\n iframeSrc,\n iframeSrcDoc,\n isGenerating,\n generationProgress,\n generationDocumentText,\n generationStartedAt,\n onCancelGeneration,\n },\n ref\n ) => {\n const [iframeLoaded, setIframeLoaded] = useState(false);\n\n // Reset iframe loaded state when content changes\n useEffect(() => {\n setIframeLoaded(false);\n }, [iframeSrc, iframeSrcDoc]);\n\n // Handle iframe load event\n const handleIframeLoad = () => {\n setIframeLoaded(true);\n };\n\n // Handle iframe errors\n const handleIframeError = () => {\n console.warn('Iframe failed to load content');\n setIframeLoaded(false);\n };\n\n // PDF blob URLs and remote viewers can be blocked by Chromium-based browsers\n // when loaded in a sandboxed iframe. Keep sandbox only for srcDoc-based preview.\n const iframeSandbox = iframeSrcDoc\n ? 'allow-scripts allow-popups allow-forms'\n : undefined;\n\n const hasContent = Boolean(iframeSrc || iframeSrcDoc);\n\n // Full-screen loaders only when no existing content\n if (isGenerating && !hasContent) {\n return (\n <div className=\"grow\">\n <DocumentGenerationLoader\n currentStage={generationProgress?.stage}\n message={generationProgress?.message}\n documentText={generationDocumentText}\n startedAt={generationStartedAt}\n onCancel={onCancelGeneration}\n />\n </div>\n );\n }\n\n if (isLoading && !hasContent) {\n return (\n <div className=\"grow\">\n <PreviewLoading renderingLibrary=\"LibreOffice\" />\n </div>\n );\n }\n\n if (hasContent) {\n return (\n <div className=\"h-full w-full relative bg-white\">\n {/* Loading overlay */}\n {!iframeLoaded && (\n <div className=\"absolute inset-0 bg-muted/80 flex items-center justify-center z-10\">\n <div className=\"text-center\">\n <div className=\"animate-spin rounded-full h-8 w-8 border-b-2 border-foreground mx-auto mb-2\"></div>\n <p className=\"text-sm text-muted-foreground\">\n Loading preview...\n </p>\n </div>\n </div>\n )}\n {/* Generating/Rendering overlay on top of existing content */}\n {(isGenerating || isLoading) && (\n <div className=\"absolute inset-0 bg-background/60 backdrop-blur-[2px] flex items-center justify-center z-20 transition-opacity duration-200\">\n <GenerationOverlay\n mode={isGenerating ? 'generating' : 'rendering'}\n message={isGenerating ? generationProgress?.message : undefined}\n startedAt={isGenerating ? generationStartedAt : undefined}\n onCancel={isGenerating ? onCancelGeneration : undefined}\n />\n </div>\n )}\n {/* Key forces remount when switching between srcDoc (sandboxed) and\n src (blob URL, no sandbox) to avoid stale sandbox race condition */}\n <iframe\n key={iframeSrcDoc ? 'srcdoc' : 'src'}\n ref={ref}\n className=\"w-full h-full border-0\"\n style={{\n backgroundColor: 'white',\n // Fade in after load to prevent flash\n opacity: iframeLoaded ? 1 : 0,\n transition: 'opacity 0.2s ease-in-out',\n }}\n src={iframeSrc}\n srcDoc={iframeSrcDoc}\n onLoad={handleIframeLoad}\n onError={handleIframeError}\n // Security: sandbox srcDoc to prevent XSS from rendered HTML.\n // Blob URLs (src) must NOT be sandboxed without allow-same-origin.\n sandbox={iframeSandbox}\n // Accessibility\n title=\"Document preview\"\n aria-label={`Preview of rendered ${FORMAT_LABEL.toLowerCase()}`}\n />\n </div>\n );\n }\n return null;\n }\n);\n\nPreviewFrame.displayName = 'PreviewFrame';\nexport const PreviewFrameMemoized = React.memo(PreviewFrame);\n","import React from 'react';\nimport { AlertTriangle, Info, ChevronRight } from 'lucide-react';\nimport type { GenerationWarning } from '../../store/output-store';\n\ninterface WarningsPanelProps {\n warnings: GenerationWarning[] | null | undefined;\n className?: string;\n}\n\nexport function WarningsPanel({ warnings, className }: WarningsPanelProps) {\n const [isExpanded, setIsExpanded] = React.useState(false);\n\n // Quality findings arrive as warnings too, and counting them here is what\n // made a stock deck announce \"48 warnings\" for forty-eight advisory infos.\n // They belong to QualityPanel; callers should already have split them out,\n // but one that forgets must not resurrect that bar.\n const reportable = React.useMemo(\n () => (warnings ?? []).filter((w) => w.component !== 'quality'),\n [warnings]\n );\n\n if (reportable.length === 0) {\n return null;\n }\n\n return (\n <div className={className}>\n <button\n type=\"button\"\n onClick={() => setIsExpanded(!isExpanded)}\n className=\"flex w-full items-center gap-2 rounded-sm border border-transparent bg-warning/10 px-3 py-1.5 text-left transition-colors hover:bg-warning/20\"\n >\n <ChevronRight\n className={`h-3.5 w-3.5 text-warning transition-transform flex-shrink-0 ${isExpanded ? 'rotate-90' : ''}`}\n />\n <AlertTriangle className=\"h-3.5 w-3.5 text-warning flex-shrink-0\" />\n <span className=\"text-xs font-medium text-warning\">\n {reportable.length} warning{reportable.length !== 1 ? 's' : ''}\n </span>\n </button>\n\n {isExpanded && (\n <div className=\"mt-1.5 space-y-1.5\">\n {reportable.map((warning, index) => (\n <div\n key={index}\n className=\"flex items-start gap-2 rounded-sm border bg-card px-3 py-2\"\n >\n {warning.severity === 'info' ? (\n <Info className=\"h-3.5 w-3.5 mt-0.5 text-data-blue flex-shrink-0\" />\n ) : (\n <AlertTriangle className=\"h-3.5 w-3.5 mt-0.5 text-warning flex-shrink-0\" />\n )}\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-1.5\">\n <code className=\"text-[11px] font-medium text-warning bg-warning/15 px-1 py-0.5 rounded-sm\">\n {warning.component}\n </code>\n {warning.severity === 'info' && (\n <span className=\"text-[10px] uppercase tracking-wide text-data-blue font-medium\">\n info\n </span>\n )}\n </div>\n <p className=\"mt-0.5 text-xs text-muted-foreground leading-relaxed\">\n {warning.message}\n </p>\n {warning.context && Object.keys(warning.context).length > 0 && (\n <details className=\"mt-1.5\">\n <summary className=\"text-[11px] text-muted-foreground/70 cursor-pointer hover:text-foreground\">\n Context\n </summary>\n <pre className=\"mt-1 text-[11px] bg-header-bg p-1.5 rounded-sm overflow-x-auto text-muted-foreground\">\n {JSON.stringify(warning.context, null, 2)}\n </pre>\n </details>\n )}\n </div>\n </div>\n ))}\n </div>\n )}\n </div>\n );\n}\n","import React, { useCallback, useMemo, useRef, useState } from 'react';\nimport Editor from '@monaco-editor/react';\nimport type { editor } from 'monaco-editor';\nimport { AlertTriangle, RotateCcw } from 'lucide-react';\nimport { useTheme } from '../theme-provider';\nimport { cn } from '../../lib/utils';\nimport { FORMAT } from '../../lib/env';\nimport {\n EMPTY_POLICY_TEXT,\n parseQualityPolicy,\n} from '../../lib/quality-policy';\nimport { QUALITY_POLICY_MODEL_PATH } from '../../lib/quality-policy-schema';\nimport { rulesForFormat } from '../../lib/quality-rules';\nimport { useSettingsStore } from '../../store/settings-store-provider';\n\n/**\n * Hand-written run policy: per-rule severity, parameters, suppressions.\n *\n * A JSON editor rather than a row of controls, because the contract is wider\n * than a form would stay honest about — suppressions carry pointers and a\n * reason, and rule parameters differ per rule. The schema registered in\n * `monaco-config` gives completion over the real rule ids, so this is closer to\n * a guided form than a text box.\n */\nexport function QualityPolicyEditor({\n className,\n}: {\n className?: string;\n}): React.JSX.Element {\n const { resolvedTheme } = useTheme();\n const policies = useSettingsStore((s) => s.qualityPolicies);\n const setSettings = useSettingsStore((s) => s.setSettings);\n const stored = policies?.[FORMAT];\n\n // The editor is uncontrolled after mount: re-feeding `value` on every\n // keystroke would fight the model and jump the cursor.\n const [text, setText] = useState(stored ?? EMPTY_POLICY_TEXT);\n const parsed = useMemo(() => parseQualityPolicy(text), [text]);\n const ruleIds = useMemo(() => rulesForFormat().map((rule) => rule.id), []);\n\n const commit = useCallback(\n (next: string) => {\n setText(next);\n // Persist the text, not the parsed policy: half-typed JSON is the normal\n // state of an editor and losing it on a reload would be worse than\n // carrying something the run will ignore until it parses.\n setSettings({ qualityPolicies: { ...policies, [FORMAT]: next } });\n },\n [policies, setSettings]\n );\n\n // The editor is uncontrolled, so `text` is not what is on screen: Reset has\n // to write the model. Without it the stored policy emptied, the caption\n // under the box said so, and the old JSON stayed visible — the button\n // looked like it did nothing.\n const editorRef = useRef<editor.IStandaloneCodeEditor | null>(null);\n const reset = useCallback(() => {\n const instance = editorRef.current;\n // `setValue` raises a content change, so the ordinary `onChange` commits\n // it. The direct call is for a Reset pressed before the editor mounted.\n if (instance) instance.setValue(EMPTY_POLICY_TEXT);\n else commit(EMPTY_POLICY_TEXT);\n }, [commit]);\n\n return (\n <div className={cn('flex min-w-0 flex-col gap-2', className)}>\n <div className=\"flex items-center justify-between gap-2\">\n <span className=\"text-[11px] leading-snug text-muted-foreground\">\n Rule severity, parameters and suppressions. The gate and profile stay\n with their controls above.\n </span>\n <button\n type=\"button\"\n onClick={reset}\n // A no-op Reset reads as a broken Reset; say so instead.\n disabled={text === EMPTY_POLICY_TEXT}\n title={\n text === EMPTY_POLICY_TEXT\n ? 'The policy is already empty'\n : 'Clear the policy back to an empty one'\n }\n className={cn(\n 'flex flex-shrink-0 items-center gap-1 rounded-sm px-1.5 py-0.5',\n 'text-[11px] font-medium text-muted-foreground transition-colors',\n 'hover:bg-accent hover:text-foreground',\n 'focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-none',\n 'disabled:pointer-events-none disabled:opacity-40'\n )}\n >\n <RotateCcw className=\"h-3 w-3\" aria-hidden=\"true\" />\n Reset\n </button>\n </div>\n\n <div className=\"overflow-hidden rounded-sm border\">\n <Editor\n height=\"180px\"\n language=\"json\"\n path={QUALITY_POLICY_MODEL_PATH}\n theme={resolvedTheme === 'dark' ? 'vs-dark' : 'vs'}\n defaultValue={text}\n onMount={(instance) => {\n editorRef.current = instance;\n }}\n onChange={(value) => commit(value ?? '')}\n options={{\n minimap: { enabled: false },\n lineNumbers: 'off',\n folding: false,\n scrollBeyondLastLine: false,\n fontSize: 11,\n lineHeight: 17,\n tabSize: 2,\n renderLineHighlight: 'none',\n overviewRulerLanes: 0,\n scrollbar: { verticalScrollbarSize: 8, horizontalScrollbarSize: 8 },\n padding: { top: 8, bottom: 8 },\n automaticLayout: true,\n }}\n />\n </div>\n\n {parsed.ok ? (\n <p className=\"text-[11px] leading-snug text-muted-foreground\">\n {parsed.policy\n ? 'Applied to every analysis and build.'\n : 'Empty — the profile decides on its own.'}\n </p>\n ) : (\n <p className=\"flex items-start gap-1.5 text-[11px] leading-snug text-destructive\">\n <AlertTriangle\n className=\"mt-0.5 h-3 w-3 flex-shrink-0\"\n aria-hidden=\"true\"\n />\n {/* An unusable policy is not sent, so the run keeps the last good one\n rather than failing every keystroke while it is being typed. */}\n <span>{parsed.error} Until this parses, the run ignores it.</span>\n </p>\n )}\n\n <details className=\"text-[11px] text-muted-foreground\">\n <summary className=\"cursor-pointer hover:text-foreground\">\n Rules in this format\n </summary>\n <ul className=\"mt-1 space-y-0.5 pl-3\">\n {ruleIds.map((id) => (\n <li key={id} className=\"font-mono text-[10px]\">\n {id}\n </li>\n ))}\n </ul>\n </details>\n </div>\n );\n}\n","import React, { useId } from 'react';\nimport { Eye, ShieldAlert, SlidersHorizontal } from 'lucide-react';\nimport { Label } from '../ui/label';\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '../ui/select';\nimport { FORMAT, type FormatName } from '../../lib/env';\nimport { cn } from '../../lib/utils';\nimport { QualityPolicyEditor } from './quality-policy-editor';\nimport type { Settings } from '../../lib/types';\nimport { useSettingsStore } from '../../store/settings-store-provider';\n\ntype QualityGate = NonNullable<Settings['qualityGate']>;\ntype QualityMinSeverity = NonNullable<Settings['qualityMinSeverity']>;\n\ntype Choice<T extends string> = {\n value: T;\n label: string;\n description: string;\n};\n\n/**\n * Radix refuses an empty option value, and `undefined` is how the store spells\n * \"let the format choose\", so the default option needs a stand-in id that never\n * reaches the server.\n */\nconst DEFAULT_PROFILE_VALUE = '__default__';\n\n/**\n * Scoped by format on purpose: a docx profile named on a presentation makes the\n * server reject the whole run as profile-incompatible, so the author must never\n * be able to pick one from the wrong list.\n */\nconst PROFILES: Record<FormatName, readonly Choice<string>[]> = {\n docx: [\n {\n value: 'executive-report',\n label: 'Executive report',\n description: 'Short decision document with strict outline continuity',\n },\n {\n value: 'technical-report',\n label: 'Technical report',\n description:\n 'Numbered sections under a running head, a source under every figure, every size on the theme scale, at least one chart or table',\n },\n {\n value: 'legal-appendix',\n label: 'Legal appendix',\n description: 'Dense appendix: preserve integrity without editorial taste',\n },\n {\n value: 'general',\n label: 'General',\n description:\n 'The format default: integrity and information design, nothing required by structure',\n },\n ],\n pptx: [\n {\n value: 'executive-presentation',\n label: 'Executive presentation',\n description: 'Decision deck optimized for scan speed and projection',\n },\n {\n value: 'technical-presentation',\n label: 'Technical presentation',\n description: 'Portable professional presentation defaults',\n },\n ],\n};\n\n/** The profile the server falls back to, so \"Default\" can name what it means. */\nconst DEFAULT_PROFILE_ID: Record<FormatName, string> = {\n docx: 'general',\n pptx: 'technical-presentation',\n};\n\n/**\n * Every label states the consequence, because the gate is the one control here\n * that turns a report into a failed build.\n */\nconst GATES: readonly Choice<QualityGate>[] = [\n {\n value: 'none',\n label: 'Never blocks',\n description: 'Findings are reported and the run always finishes',\n },\n {\n value: 'error',\n label: 'Blocks on errors',\n description: 'Generation fails when a finding is an error',\n },\n {\n value: 'warning',\n label: 'Blocks on warnings',\n description: 'Generation fails on any warning or error',\n },\n {\n value: 'info',\n label: 'Blocks on anything',\n description: 'Generation fails on any finding, info included',\n },\n];\n\nconst MIN_SEVERITIES: readonly Choice<QualityMinSeverity>[] = [\n {\n value: 'error',\n label: 'Errors only',\n description: 'Warnings and info stay hidden',\n },\n {\n value: 'warning',\n label: 'Warnings and errors',\n description: 'Info stays hidden',\n },\n {\n value: 'info',\n label: 'Everything',\n description: 'Every finding the analysis produced',\n },\n];\n\nconst TRIGGER_CLASS =\n 'h-8 min-h-0 w-full gap-1.5 px-2 text-xs [&>span]:truncate [&>span]:whitespace-nowrap';\n\nconst CONTENT_CLASS =\n 'max-w-[min(20rem,var(--radix-select-content-available-width))]';\n\nconst LABEL_CLASS = 'flex items-center gap-1.5 text-xs';\n\nconst HELP_CLASS = 'text-[11px] leading-snug text-muted-foreground';\n\nconst DEFAULT_PROFILE_CHOICE: Choice<string> = {\n value: DEFAULT_PROFILE_VALUE,\n label: 'Default',\n description: `The format's own profile (${DEFAULT_PROFILE_ID[FORMAT]})`,\n};\n\nfunction SectionHeading({ children }: { children: React.ReactNode }) {\n return (\n <span className=\"text-[10px] font-semibold tracking-wide text-muted-foreground uppercase\">\n {children}\n </span>\n );\n}\n\nfunction ChoiceRow({ choice }: { choice: Choice<string> }) {\n return (\n <span className=\"flex min-w-0 flex-col gap-0.5\">\n <span className=\"font-medium\">{choice.label}</span>\n <span className={HELP_CLASS}>{choice.description}</span>\n </span>\n );\n}\n\n/**\n * Profile, gate and display filter for the quality analysis. The gate and the\n * filter get mistaken for each other constantly, so they sit in separate\n * sections instead of forming one row of look-alike dropdowns.\n */\nexport function QualityControls({\n className,\n}: {\n className?: string;\n}): React.JSX.Element {\n const fieldId = useId();\n const profileIds = useSettingsStore((s) => s.qualityProfileIds);\n const profileId = profileIds?.[FORMAT];\n const gate = useSettingsStore((s) => s.qualityGate) ?? 'none';\n const minSeverity =\n useSettingsStore((s) => s.qualityMinSeverity) ?? 'warning';\n const setSettings = useSettingsStore((s) => s.setSettings);\n\n const profiles = PROFILES[FORMAT];\n const storedProfile = profiles.find((choice) => choice.value === profileId);\n const selectedProfile = storedProfile ?? DEFAULT_PROFILE_CHOICE;\n const selectedGate =\n GATES.find((choice) => choice.value === gate) ?? GATES[0];\n const selectedSeverity =\n MIN_SEVERITIES.find((choice) => choice.value === minSeverity) ??\n MIN_SEVERITIES[1];\n\n return (\n <div className={cn('flex w-full min-w-0 flex-col gap-5', className)}>\n <div className=\"flex min-w-0 flex-col gap-3\">\n <SectionHeading>Run policy</SectionHeading>\n\n <div className=\"grid min-w-0 gap-1.5\">\n <Label htmlFor={`${fieldId}-profile`} className={LABEL_CLASS}>\n <SlidersHorizontal className=\"h-3.5 w-3.5 shrink-0 opacity-60\" />\n Profile\n </Label>\n <Select\n value={selectedProfile.value}\n onValueChange={(value) =>\n // Written under this format's key only: the other playground's\n // choice lives in the same persisted object and must survive.\n setSettings({\n qualityProfileIds: {\n ...profileIds,\n [FORMAT]: value === DEFAULT_PROFILE_VALUE ? undefined : value,\n },\n })\n }\n >\n <SelectTrigger\n id={`${fieldId}-profile`}\n aria-describedby={`${fieldId}-profile-help`}\n className={TRIGGER_CLASS}\n >\n <SelectValue>\n <span className=\"font-medium\">{selectedProfile.label}</span>\n </SelectValue>\n </SelectTrigger>\n <SelectContent className={CONTENT_CLASS}>\n <SelectItem value={DEFAULT_PROFILE_VALUE} className=\"text-xs\">\n <ChoiceRow choice={DEFAULT_PROFILE_CHOICE} />\n </SelectItem>\n {profiles.map((choice) => (\n <SelectItem\n key={choice.value}\n value={choice.value}\n className=\"text-xs\"\n >\n <ChoiceRow choice={choice} />\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n <p id={`${fieldId}-profile-help`} className={HELP_CLASS}>\n {selectedProfile.description}\n </p>\n </div>\n\n <div className=\"grid min-w-0 gap-1.5\">\n <Label htmlFor={`${fieldId}-gate`} className={LABEL_CLASS}>\n <ShieldAlert className=\"h-3.5 w-3.5 shrink-0 opacity-60\" />\n Gate\n </Label>\n <Select\n value={selectedGate.value}\n onValueChange={(value) =>\n setSettings({ qualityGate: value as QualityGate })\n }\n >\n <SelectTrigger\n id={`${fieldId}-gate`}\n aria-describedby={`${fieldId}-gate-help`}\n className={TRIGGER_CLASS}\n >\n <SelectValue>\n <span className=\"font-medium\">{selectedGate.label}</span>\n </SelectValue>\n </SelectTrigger>\n <SelectContent className={CONTENT_CLASS}>\n {GATES.map((choice) => (\n <SelectItem\n key={choice.value}\n value={choice.value}\n className=\"text-xs\"\n >\n <ChoiceRow choice={choice} />\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n <p id={`${fieldId}-gate-help`} className={HELP_CLASS}>\n {selectedGate.description}.\n </p>\n </div>\n </div>\n\n <div className=\"h-px shrink-0 bg-border/60\" />\n\n <div className=\"flex min-w-0 flex-col gap-3\">\n <SectionHeading>Rule policy</SectionHeading>\n <QualityPolicyEditor />\n </div>\n\n <div className=\"h-px shrink-0 bg-border/60\" />\n\n <div className=\"flex min-w-0 flex-col gap-3\">\n <SectionHeading>Panel display</SectionHeading>\n\n <div className=\"grid min-w-0 gap-1.5\">\n <Label htmlFor={`${fieldId}-severity`} className={LABEL_CLASS}>\n <Eye className=\"h-3.5 w-3.5 shrink-0 opacity-60\" />\n Show\n </Label>\n <Select\n value={selectedSeverity.value}\n onValueChange={(value) =>\n setSettings({ qualityMinSeverity: value as QualityMinSeverity })\n }\n >\n <SelectTrigger\n id={`${fieldId}-severity`}\n aria-describedby={`${fieldId}-severity-help`}\n className={TRIGGER_CLASS}\n >\n <SelectValue>\n <span className=\"font-medium\">{selectedSeverity.label}</span>\n </SelectValue>\n </SelectTrigger>\n <SelectContent className={CONTENT_CLASS}>\n {MIN_SEVERITIES.map((choice) => (\n <SelectItem\n key={choice.value}\n value={choice.value}\n className=\"text-xs\"\n >\n <ChoiceRow choice={choice} />\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n <p id={`${fieldId}-severity-help`} className={HELP_CLASS}>\n Filters this panel only. It never changes what the run does.\n </p>\n </div>\n </div>\n </div>\n );\n}\n","/**\n * RFC 6901 JSON Pointer helpers. Quality findings address the authored\n * document by pointer ('/children/0/props/fontSize'); the playground needs\n * those pointers both as character ranges (to reveal the location in Monaco)\n * and as path arrays (to mutate the parsed document).\n *\n * Built on jsonc-parser, like document-outline.ts, because `parseTree` is\n * error-tolerant: the editor text is frequently mid-edit and temporarily\n * invalid, and a pointer lookup must degrade to null rather than throw.\n */\nimport { parseTree, findNodeAtLocation, type Node } from 'jsonc-parser';\n\n/**\n * A segment is an array index only when it is a canonical non-negative\n * integer. '01' and '-1' stay strings so they can still match an object key\n * spelled exactly that way.\n */\nconst ARRAY_INDEX_RE = /^(?:0|[1-9][0-9]*)$/;\n\n/** RFC 6901 segment decode: ~1 -> '/', ~0 -> '~'. Order matters. */\nexport function decodePointerSegment(segment: string): string {\n return segment.replace(/~1/g, '/').replace(/~0/g, '~');\n}\n\n/** RFC 6901 segment encode: '~' -> ~0, '/' -> ~1. Order matters. */\nfunction encodePointerSegment(segment: string): string {\n return segment.replace(/~/g, '~0').replace(/\\//g, '~1');\n}\n\n/** '' -> []. '/a/0/b' -> ['a', 0, 'b']. Numeric segments become numbers. */\nexport function pointerToPathArray(pointer: string): (string | number)[] {\n if (pointer === '') return [];\n // Tolerate a missing leading '/' so a caller-built 'a/b' still resolves;\n // splitting a well-formed pointer always yields an empty first element.\n const body = pointer.startsWith('/') ? pointer.slice(1) : pointer;\n return body.split('/').map((raw) => {\n const decoded = decodePointerSegment(raw);\n return ARRAY_INDEX_RE.test(decoded) ? Number(decoded) : decoded;\n });\n}\n\n/** Inverse of pointerToPathArray, with ~ and / re-escaped. */\nexport function pathArrayToPointer(path: readonly (string | number)[]): string {\n return path\n .map((segment) => `/${encodePointerSegment(String(segment))}`)\n .join('');\n}\n\n/**\n * Resolves one segment below `node`. A numeric-looking OBJECT key is\n * ambiguous — pointerToPathArray turns '0' into the number 0, which\n * findNodeAtLocation only matches against arrays — so a failed numeric lookup\n * retries as the string key before giving up.\n */\nfunction resolveSegment(\n node: Node,\n segment: string | number\n): Node | undefined {\n const hit = findNodeAtLocation(node, [segment]);\n if (hit || typeof segment !== 'number') return hit;\n return findNodeAtLocation(node, [String(segment)]);\n}\n\n/**\n * Character offsets of the VALUE the pointer addresses, in the given JSON\n * text. Returns null when the pointer does not resolve.\n *\n * Callers pass Monaco MODEL text, which may contain collapsed-string\n * sentinels (`§jtoc:<id>§`). Those are ordinary JSON string contents, so the\n * parse succeeds and the offsets line up with what is on screen — do not\n * \"fix\" this by expanding them first.\n */\nexport function findPointerRange(\n text: string,\n pointer: string\n): { start: number; end: number } | null {\n if (!text.trim()) return null;\n let node: Node | undefined;\n try {\n node = parseTree(text, [], { allowTrailingComma: true });\n if (!node) return null;\n for (const segment of pointerToPathArray(pointer)) {\n node = resolveSegment(node, segment);\n if (!node) return null;\n }\n } catch {\n // parseTree is error-tolerant, but a pointer must never take the editor\n // down over text the user is halfway through typing.\n return null;\n }\n return { start: node.offset, end: node.offset + node.length };\n}\n","/**\n * RFC 6902 JSON Patch, applied to the parsed playground document.\n *\n * Quality findings can carry the operations that repair the defect they\n * report, which is what the \"Apply fix\" affordance runs. Two properties make\n * that safe to hand a user: the patch is all-or-nothing (a half-applied repair\n * is worse than none), and the caller's object graph is never mutated, so the\n * editor can diff or discard the result.\n */\nimport { pathArrayToPointer, pointerToPathArray } from './json-pointer';\nimport type { QualityFixOp } from './quality-findings';\n\nexport type ApplyFixesResult =\n | { ok: true; doc: unknown; applied: number }\n | { ok: false; error: string };\n\nconst SUPPORTED_OPS = [\n 'add',\n 'remove',\n 'replace',\n 'move',\n 'copy',\n 'test',\n] as const;\n\ntype SupportedOp = (typeof SUPPORTED_OPS)[number];\n\ntype Segment = string | number;\n\n/**\n * Fallible result threaded through every helper below. Failures are values\n * because the public contract forbids throwing, and an exception escaping mid\n * patch would also make \"all-or-nothing\" a claim we could not keep.\n */\ntype Step<T> = { ok: true; value: T } | { ok: false; error: string };\n\n/**\n * Apply RFC 6902 operations in order. All-or-nothing: if any operation fails\n * the original document is left untouched and an error is returned.\n */\nexport function applyQualityFixes(\n doc: unknown,\n fixes: readonly QualityFixOp[]\n): ApplyFixesResult {\n try {\n let next = doc;\n for (let index = 0; index < fixes.length; index++) {\n const outcome = applyOne(next, fixes[index], index);\n if (!outcome.ok) return { ok: false, error: outcome.error };\n next = outcome.value;\n }\n return { ok: true, doc: next, applied: fixes.length };\n } catch (error) {\n // Fixes arrive over the network and the document is whatever the user\n // typed, so an unforeseen shape must degrade to a failed patch rather\n // than take the editor down.\n return { ok: false, error: `quality fix failed: ${describeError(error)}` };\n }\n}\n\n/**\n * True when every op in the list is one this module can apply. A missing or\n * empty list is false: there is nothing to apply, so the caller must not\n * surface a fix affordance for it.\n */\nexport function canApplyFixes(\n fixes: readonly QualityFixOp[] | undefined\n): boolean {\n if (!fixes || fixes.length === 0) return false;\n return fixes.every((fix) => {\n if (!isSupportedOp(fix.op)) return false;\n // A move or copy without a source can never resolve, however well-formed\n // the rest of the operation looks.\n if (fix.op === 'move' || fix.op === 'copy') {\n return typeof fix.from === 'string';\n }\n return true;\n });\n}\n\nfunction applyOne(\n doc: unknown,\n fix: QualityFixOp,\n index: number\n): Step<unknown> {\n const label = `fix #${index + 1} (${String(fix.op)} \"${String(fix.path)}\")`;\n const op = fix.op;\n if (!isSupportedOp(op)) {\n return fail(`${label}: unsupported operation \"${String(op)}\"`);\n }\n\n const path = pointerToPathArray(fix.path);\n\n switch (op) {\n case 'add':\n return addAtPath(doc, path, fix.value, label);\n\n case 'replace':\n return replaceAtPath(doc, path, fix.value, label);\n\n case 'remove': {\n const removed = removeAtPath(doc, path, label);\n if (!removed.ok) return removed;\n return step(removed.value.doc);\n }\n\n case 'copy': {\n const from = readFrom(fix, label);\n if (!from.ok) return from;\n const source = resolvePath(doc, from.value.path);\n if (!source.ok) return fail(`${label}: ${source.error}`);\n // The copied subtree is shared rather than deep-cloned: every write in\n // this module clones the path it touches, so neither reference can ever\n // observe an edit made through the other.\n return addAtPath(doc, path, source.value, label);\n }\n\n case 'move': {\n const from = readFrom(fix, label);\n if (!from.ok) return from;\n if (samePath(from.value.path, path)) return step(doc);\n if (isProperPrefix(from.value.path, path)) {\n return fail(\n `${label}: ${describePointer(from.value.path)} cannot be moved ` +\n 'into its own child'\n );\n }\n // RFC 6902 removes first, so a move inside one array is expressed\n // against post-removal indices.\n const removed = removeAtPath(doc, from.value.path, label);\n if (!removed.ok) return removed;\n return addAtPath(removed.value.doc, path, removed.value.removed, label);\n }\n\n case 'test': {\n const actual = resolvePath(doc, path);\n if (!actual.ok) return fail(`${label}: ${actual.error}`);\n if (!deepEqual(actual.value, fix.value)) {\n return fail(`${label}: test failed, the value at the path differs`);\n }\n return step(doc);\n }\n }\n}\n\nfunction addAtPath(\n doc: unknown,\n path: readonly Segment[],\n value: unknown,\n label: string\n): Step<unknown> {\n // An empty pointer addresses the whole document.\n if (path.length === 0) return step(value);\n const last = path[path.length - 1];\n return updateParent(doc, path, label, (parent) => {\n if (Array.isArray(parent)) {\n const index = last === '-' ? parent.length : toIndex(last);\n if (index === null) {\n return fail(`${label}: \"${String(last)}\" is not an array index`);\n }\n if (index > parent.length) {\n return fail(`${label}: index ${index} is past the end of the array`);\n }\n const next = cloneContainer(parent) as unknown[];\n // `add` inserts and only `replace` overwrites. Getting this backwards\n // drops the element that was there and silently corrupts the document.\n next.splice(index, 0, value);\n return step(next);\n }\n if (isPlainObject(parent)) {\n const next = cloneContainer(parent) as Record<string, unknown>;\n next[String(last)] = value;\n return step(next);\n }\n return fail(\n `${label}: ${describePointer(path.slice(0, -1))} is not an object or array`\n );\n });\n}\n\nfunction replaceAtPath(\n doc: unknown,\n path: readonly Segment[],\n value: unknown,\n label: string\n): Step<unknown> {\n if (path.length === 0) return step(value);\n const last = path[path.length - 1];\n return updateParent(doc, path, label, (parent) => {\n if (Array.isArray(parent)) {\n const index = toIndex(last);\n if (index === null || index >= parent.length) {\n return fail(\n `${label}: \"${String(last)}\" is not an existing array index`\n );\n }\n const next = cloneContainer(parent) as unknown[];\n next[index] = value;\n return step(next);\n }\n if (isPlainObject(parent)) {\n const key = String(last);\n if (!hasOwn(parent, key)) {\n return fail(`${label}: \"${key}\" does not exist`);\n }\n const next = cloneContainer(parent) as Record<string, unknown>;\n next[key] = value;\n return step(next);\n }\n return fail(\n `${label}: ${describePointer(path.slice(0, -1))} is not an object or array`\n );\n });\n}\n\nfunction removeAtPath(\n doc: unknown,\n path: readonly Segment[],\n label: string\n): Step<{ doc: unknown; removed: unknown }> {\n if (path.length === 0) {\n return fail(`${label}: the whole document cannot be removed`);\n }\n const last = path[path.length - 1];\n let removed: unknown;\n const next = updateParent(doc, path, label, (parent) => {\n if (Array.isArray(parent)) {\n const index = toIndex(last);\n if (index === null || index >= parent.length) {\n return fail(\n `${label}: \"${String(last)}\" is not an existing array index`\n );\n }\n const clone = cloneContainer(parent) as unknown[];\n removed = clone.splice(index, 1)[0];\n return step(clone);\n }\n if (isPlainObject(parent)) {\n const key = String(last);\n if (!hasOwn(parent, key)) {\n return fail(`${label}: \"${key}\" does not exist`);\n }\n const clone = cloneContainer(parent) as Record<string, unknown>;\n removed = clone[key];\n delete clone[key];\n return step(clone);\n }\n return fail(\n `${label}: ${describePointer(path.slice(0, -1))} is not an object or array`\n );\n });\n if (!next.ok) return next;\n return step({ doc: next.value, removed });\n}\n\n/**\n * Walk to the container that owns the last segment of `path`, hand it to\n * `update`, and rebuild the document around what comes back. Only containers\n * on the path are cloned — every sibling subtree stays shared, the structural\n * sharing `doc-mutations.ts` relies on to leave the caller's graph intact.\n */\nfunction updateParent(\n doc: unknown,\n path: readonly Segment[],\n label: string,\n update: (parent: unknown) => Step<unknown>\n): Step<unknown> {\n return rewrite(doc, path.slice(0, -1), 0, label, update);\n}\n\nfunction rewrite(\n node: unknown,\n parentPath: readonly Segment[],\n depth: number,\n label: string,\n update: (parent: unknown) => Step<unknown>\n): Step<unknown> {\n if (depth === parentPath.length) return update(node);\n\n const here = () => describePointer(parentPath.slice(0, depth + 1));\n const segment = parentPath[depth];\n\n if (Array.isArray(node)) {\n const index = toIndex(segment);\n if (index === null || index >= node.length) {\n return fail(`${label}: ${here()} does not exist`);\n }\n const child = rewrite(node[index], parentPath, depth + 1, label, update);\n if (!child.ok) return child;\n const next = cloneContainer(node) as unknown[];\n next[index] = child.value;\n return step(next);\n }\n\n if (isPlainObject(node)) {\n const key = String(segment);\n // Writing through a missing parent would invent structure the fix never\n // described, so it fails instead of materializing containers.\n if (!hasOwn(node, key)) {\n return fail(`${label}: ${here()} does not exist`);\n }\n const child = rewrite(node[key], parentPath, depth + 1, label, update);\n if (!child.ok) return child;\n const next = cloneContainer(node) as Record<string, unknown>;\n next[key] = child.value;\n return step(next);\n }\n\n return fail(\n `${label}: ${describePointer(\n parentPath.slice(0, depth)\n )} is not an object or array`\n );\n}\n\nfunction resolvePath(doc: unknown, path: readonly Segment[]): Step<unknown> {\n let current = doc;\n for (let depth = 0; depth < path.length; depth++) {\n const segment = path[depth];\n if (Array.isArray(current)) {\n const index = toIndex(segment);\n if (index === null || index >= current.length) {\n return fail(\n `${describePointer(path.slice(0, depth + 1))} does not exist`\n );\n }\n current = current[index];\n continue;\n }\n if (isPlainObject(current)) {\n const key = String(segment);\n if (!hasOwn(current, key)) {\n return fail(\n `${describePointer(path.slice(0, depth + 1))} does not exist`\n );\n }\n current = current[key];\n continue;\n }\n return fail(\n `${describePointer(path.slice(0, depth))} is not an object or array`\n );\n }\n return step(current);\n}\n\nfunction readFrom(\n fix: QualityFixOp,\n label: string\n): Step<{ pointer: string; path: Segment[] }> {\n const pointer = fix.from;\n if (typeof pointer !== 'string') {\n return fail(`${label}: a \"from\" pointer is required`);\n }\n return step({ pointer, path: pointerToPathArray(pointer) });\n}\n\n/**\n * Shallow-clone a container before writing into it — the `cloneContainer`\n * idiom from `doc-mutations.ts`, minus its materialization of missing levels,\n * which RFC 6902 forbids.\n */\nfunction cloneContainer(\n value: readonly unknown[] | Record<string, unknown>\n): unknown[] | Record<string, unknown> {\n if (Array.isArray(value)) return [...value];\n return { ...(value as Record<string, unknown>) };\n}\n\n/**\n * Coerce a pointer segment to an array index. The pointer parser already\n * hands back numbers for canonical indices, but a segment that survived as a\n * string ('01', '-', 'title') addresses nothing in an array.\n */\nfunction toIndex(segment: Segment): number | null {\n if (typeof segment === 'number') {\n return Number.isInteger(segment) && segment >= 0 ? segment : null;\n }\n return /^(?:0|[1-9][0-9]*)$/.test(segment) ? Number(segment) : null;\n}\n\nfunction describePointer(path: readonly Segment[]): string {\n return path.length === 0\n ? 'the document root'\n : `\"${pathArrayToPointer(path)}\"`;\n}\n\nfunction isSupportedOp(op: unknown): op is SupportedOp {\n return (SUPPORTED_OPS as readonly unknown[]).includes(op);\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction hasOwn(value: object, key: string): boolean {\n return Object.prototype.hasOwnProperty.call(value, key);\n}\n\nfunction samePath(a: readonly Segment[], b: readonly Segment[]): boolean {\n return (\n a.length === b.length && a.every((seg, i) => String(seg) === String(b[i]))\n );\n}\n\nfunction isProperPrefix(\n prefix: readonly Segment[],\n path: readonly Segment[]\n): boolean {\n if (prefix.length >= path.length) return false;\n return prefix.every((seg, i) => String(seg) === String(path[i]));\n}\n\nfunction deepEqual(a: unknown, b: unknown): boolean {\n if (a === b) return true;\n if (Array.isArray(a) || Array.isArray(b)) {\n if (!Array.isArray(a) || !Array.isArray(b)) return false;\n if (a.length !== b.length) return false;\n return a.every((item, index) => deepEqual(item, b[index]));\n }\n if (isPlainObject(a) && isPlainObject(b)) {\n const keys = Object.keys(a);\n if (keys.length !== Object.keys(b).length) return false;\n return keys.every((key) => hasOwn(b, key) && deepEqual(a[key], b[key]));\n }\n return false;\n}\n\nfunction describeError(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nfunction step<T>(value: T): Step<T> {\n return { ok: true, value };\n}\n\nfunction fail(error: string): { ok: false; error: string } {\n return { ok: false, error };\n}\n","import React from 'react';\nimport {\n AlertTriangle,\n CheckCircle2,\n ChevronRight,\n Crosshair,\n Info,\n ShieldAlert,\n Wand2,\n XCircle,\n} from 'lucide-react';\nimport { canApplyFixes } from '../../lib/quality-fixes';\nimport {\n certaintyLabel,\n countBySeverity,\n filterByMinSeverity,\n groupByCategory,\n type QualityEvidence,\n type QualityFinding,\n type QualitySeverity,\n} from '../../lib/quality-findings';\nimport { cn } from '../../lib/utils';\nimport type { QualityState } from '../../store/output-store';\nimport { useSettingsStore } from '../../store/settings-store-provider';\nimport { Spinner } from '../ui/spinner';\n\n/**\n * The document-quality findings panel.\n *\n * Quality findings used to land in the generic warnings list, where a stock\n * deck's two hundred info-severity notes were all counted and labelled\n * \"warnings\". Keeping the severities apart is the whole reason this panel\n * exists, so every count it renders is split by severity rather than totalled.\n */\n\n/**\n * Rows mounted before the \"Show all\" expander takes over. A stock deck\n * produces roughly fifty findings and a dense one over two hundred; mounting\n * every row makes opening the panel visibly janky.\n */\nconst ROW_CAP = 50;\n\n/** Stable identity so the memos below do not re-run on every parent render. */\nconst EMPTY_FINDINGS: QualityFinding[] = [];\n\nconst SEVERITY_ORDER: readonly QualitySeverity[] = ['error', 'warning', 'info'];\n\nconst SEVERITY_ICONS: Record<\n QualitySeverity,\n React.ComponentType<{ className?: string }>\n> = {\n error: XCircle,\n warning: AlertTriangle,\n info: Info,\n};\n\nconst SEVERITY_TEXT: Record<QualitySeverity, string> = {\n error: 'text-destructive',\n warning: 'text-warning',\n info: 'text-data-blue',\n};\n\n/** Keys the evidence line renders itself; everything else goes behind details. */\nconst EVIDENCE_SUMMARY_KEYS = new Set(['actual', 'expected', 'unit']);\n\n/** 'info' is a mass noun, so unlike errors and warnings it takes no plural s. */\nfunction countLabel(severity: QualitySeverity, count: number): string {\n if (severity === 'info') return `${count} info`;\n return `${count} ${severity}${count === 1 ? '' : 's'}`;\n}\n\nfunction formatEvidenceValue(value: unknown, unit: string | undefined): string {\n const base =\n typeof value === 'string'\n ? value\n : typeof value === 'number' || typeof value === 'boolean'\n ? String(value)\n : JSON.stringify(value);\n return unit ? `${base} ${unit}` : base;\n}\n\n/**\n * Evidence keys beyond the actual/expected pair. The server is free to attach\n * its own extras, so the row shows the comparison a reader can act on and\n * hides the rest rather than dumping the object into the list.\n */\nfunction extraEvidence(\n evidence: QualityEvidence | undefined\n): Record<string, unknown> | null {\n if (!evidence) return null;\n const rest: Record<string, unknown> = {};\n let found = false;\n for (const [key, value] of Object.entries(evidence)) {\n if (EVIDENCE_SUMMARY_KEYS.has(key)) continue;\n rest[key] = value;\n found = true;\n }\n return found ? rest : null;\n}\n\ninterface PathChipProps {\n path: string;\n onRevealPath?: (path: string) => void;\n /** Related paths are secondary context, so they render lighter. */\n muted?: boolean;\n}\n\nfunction PathChip({ path, onRevealPath, muted }: PathChipProps) {\n const base = cn(\n 'inline-flex max-w-full items-center gap-1 rounded-sm font-mono text-[10px]',\n muted ? 'text-muted-foreground/60' : 'text-muted-foreground/80'\n );\n\n if (!onRevealPath) {\n return (\n <span className={base}>\n <span className=\"truncate\">{path}</span>\n </span>\n );\n }\n\n return (\n <button\n type=\"button\"\n onClick={() => onRevealPath(path)}\n title={`Reveal ${path} in the editor`}\n className={cn(\n base,\n // A pointer is a destination, not a label. The crosshair and the\n // underline on hover are what say so — the old chip read as metadata\n // and nobody discovered it was clickable.\n '-mx-1 px-1 py-0.5 transition-colors',\n 'hover:bg-accent hover:text-foreground hover:underline',\n 'focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-none'\n )}\n >\n <Crosshair className=\"h-2.5 w-2.5 flex-shrink-0\" aria-hidden=\"true\" />\n <span className=\"truncate\">{path}</span>\n </button>\n );\n}\n\ninterface FindingRowProps {\n finding: QualityFinding;\n onRevealPath?: (path: string) => void;\n onApplyFixes?: (finding: QualityFinding) => void;\n isApplying: boolean;\n}\n\nfunction FindingRow({\n finding,\n onRevealPath,\n onApplyFixes,\n isApplying,\n}: FindingRowProps) {\n const Icon = SEVERITY_ICONS[finding.severity] ?? Info;\n const tone = SEVERITY_TEXT[finding.severity] ?? 'text-muted-foreground';\n const certainty = certaintyLabel(finding.certainty);\n const evidence = finding.evidence;\n const hasComparison =\n evidence !== undefined &&\n (evidence.actual !== undefined || evidence.expected !== undefined);\n const rest = extraEvidence(evidence);\n const showFix = Boolean(onApplyFixes) && canApplyFixes(finding.fixes);\n const relatedPaths = finding.relatedPaths ?? [];\n\n return (\n <div className=\"rounded-sm border bg-card px-3 py-2.5\">\n {/* What is wrong, first and in plain language. The code used to lead\n here, which put the least readable thing in the most prominent slot;\n it is reference data for writing a policy, so it sits in the footer\n with the other machine-readable fields. */}\n <div className=\"flex items-start gap-2\">\n <Icon className={cn('mt-0.5 h-3.5 w-3.5 flex-shrink-0', tone)} />\n <div className=\"min-w-0 flex-1\">\n {finding.blocking && (\n <span className=\"mr-1.5 rounded-sm bg-destructive/15 px-1 py-0.5 align-[1px] text-[10px] font-medium tracking-wide text-destructive uppercase\">\n blocking\n </span>\n )}\n <span className=\"text-xs leading-relaxed text-foreground\">\n {finding.message}\n </span>\n </div>\n </div>\n\n <div className=\"mt-1.5 pl-[1.375rem]\">\n {/* Expectation before reality, matching how the message reads, and in\n words rather than the `actual · expected` pair that looked like\n debug output. */}\n {hasComparison && evidence && (\n <p className=\"text-[11px] text-muted-foreground\">\n {evidence.expected !== undefined && (\n <>\n Expected{' '}\n <span className=\"font-mono font-medium text-foreground/90\">\n {formatEvidenceValue(evidence.expected, evidence.unit)}\n </span>\n </>\n )}\n {evidence.expected !== undefined &&\n evidence.actual !== undefined && (\n <span className=\"text-muted-foreground/50\"> · </span>\n )}\n {evidence.actual !== undefined && (\n <>\n {evidence.expected === undefined ? 'Found' : 'found'}{' '}\n <span className=\"font-mono font-medium text-foreground/90\">\n {formatEvidenceValue(evidence.actual, evidence.unit)}\n </span>\n </>\n )}\n </p>\n )}\n\n {/* Advice and the button that enacts it are one thing, so they share\n one block. The button used to float in the card's top corner, an\n inch from the sentence explaining what it would do. */}\n {(finding.suggestion || showFix) && (\n <div\n className={cn(\n 'mt-1.5 flex items-center gap-2 rounded-sm bg-header-bg/70 px-2 py-1.5',\n !finding.suggestion && 'justify-end'\n )}\n >\n {finding.suggestion && (\n <p className=\"min-w-0 flex-1 text-[11px] leading-relaxed text-muted-foreground\">\n {finding.suggestion}\n </p>\n )}\n {showFix && (\n <button\n type=\"button\"\n onClick={() => onApplyFixes?.(finding)}\n disabled={isApplying}\n className={cn(\n 'flex flex-shrink-0 items-center gap-1 rounded-sm border bg-card px-1.5 py-1',\n 'text-[11px] font-medium text-foreground transition-colors',\n 'hover:bg-accent focus-visible:ring-1 focus-visible:ring-ring',\n 'focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-60'\n )}\n >\n {isApplying ? (\n <Spinner size=\"sm\" variant=\"muted\" className=\"h-3 w-3\" />\n ) : (\n <Wand2 className=\"h-3 w-3\" aria-hidden=\"true\" />\n )}\n Apply fix\n </button>\n )}\n </div>\n )}\n\n {/* Where, how sure, and what to call it in a policy. All reference:\n muted, one line, out of the way of the sentence above. The category\n is not repeated here — the group heading above already names it. */}\n <div className=\"mt-2 flex flex-wrap items-center gap-x-2.5 gap-y-1\">\n {finding.path && (\n <PathChip path={finding.path} onRevealPath={onRevealPath} />\n )}\n {relatedPaths.map((related) => (\n <PathChip\n key={related}\n path={related}\n onRevealPath={onRevealPath}\n muted\n />\n ))}\n {certainty && (\n <span\n className=\"text-[10px] text-muted-foreground/70\"\n title=\"How the analysis reached this finding\"\n >\n {certainty}\n </span>\n )}\n {finding.code && (\n <code className=\"text-[10px] text-muted-foreground/60\">\n {finding.code}\n </code>\n )}\n </div>\n\n {rest && (\n <details className=\"mt-1.5\">\n <summary className=\"cursor-pointer text-[11px] text-muted-foreground/70 hover:text-foreground\">\n More evidence\n </summary>\n <pre className=\"mt-1 overflow-x-auto rounded-sm bg-header-bg p-1.5 text-[11px] text-muted-foreground\">\n {JSON.stringify(rest, null, 2)}\n </pre>\n </details>\n )}\n </div>\n </div>\n );\n}\n\nexport interface QualityFindingsProps {\n quality: QualityState | null | undefined;\n id?: string;\n className?: string;\n /** Reveal an RFC 6901 path in the active editor. */\n onRevealPath?: (path: string) => void;\n /** Present only when the finding carries applicable fixes. */\n onApplyFixes?: (finding: QualityFinding) => void;\n /** True while a fix is being applied, to disable the button. */\n applyingFindingId?: string | null;\n}\n\n/**\n * The findings themselves, without a header of their own.\n *\n * Rendered into a floating drawer rather than into the column: the preview is\n * the thing the author is reading, and a list that pushes the page down moves\n * the document every time the analysis changes.\n */\nexport function QualityFindings({\n quality,\n id,\n className,\n onRevealPath,\n onApplyFixes,\n applyingFindingId,\n}: QualityFindingsProps): React.JSX.Element | null {\n const minSeverity = useSettingsStore((state) => state.qualityMinSeverity);\n const [showAllSeverities, setShowAllSeverities] = React.useState(false);\n const [showAllRows, setShowAllRows] = React.useState(false);\n\n const findings = quality?.findings ?? EMPTY_FINDINGS;\n const threshold: QualitySeverity = minSeverity ?? 'warning';\n\n const kept = React.useMemo(\n () => filterByMinSeverity(findings, threshold),\n [findings, threshold]\n );\n const visible = showAllSeverities ? findings : kept;\n\n const groups = React.useMemo(() => groupByCategory(visible), [visible]);\n\n const cappedGroups = React.useMemo(() => {\n if (showAllRows || visible.length <= ROW_CAP) return groups;\n let budget = ROW_CAP;\n const out: Array<{ category: string; findings: QualityFinding[] }> = [];\n for (const group of groups) {\n if (budget <= 0) break;\n const slice = group.findings.slice(0, budget);\n budget -= slice.length;\n out.push({ category: group.category, findings: slice });\n }\n return out;\n }, [groups, showAllRows, visible.length]);\n\n // Counts come from the findings actually held rather than from the server's\n // tally, so the header can never claim severities the body has no rows for.\n // `truncated` is what explains a shortfall against the server's own count.\n const counts = React.useMemo(() => countBySeverity(findings), [findings]);\n const keptCounts = React.useMemo(() => countBySeverity(kept), [kept]);\n const hiddenTotal = findings.length - kept.length;\n\n const hiddenLabel = React.useMemo(() => {\n const parts: string[] = [];\n let named = 0;\n for (const severity of SEVERITY_ORDER) {\n const n = counts[severity] - keptCounts[severity];\n if (n > 0) {\n parts.push(countLabel(severity, n));\n named += n;\n }\n }\n // Findings carrying a severity this build does not know about are dropped\n // by any threshold, and would otherwise vanish without being accounted for.\n if (named < hiddenTotal) parts.push(`${hiddenTotal - named} other`);\n return parts.join(', ');\n }, [counts, keptCounts, hiddenTotal]);\n\n // Nothing analysed yet, and nothing to report about a clean document — the\n // summary row above says that in one line.\n if (!quality) return null;\n if (\n findings.length === 0 &&\n !quality.gateError &&\n !quality.analysisError &&\n !quality.truncated\n ) {\n return null;\n }\n\n return (\n <div id={id} className={cn('space-y-1.5', className)}>\n {/* The gate refused a build the author asked for, so it explains itself\n before any finding. */}\n {quality.gateError && (\n <div className=\"flex items-start gap-2 rounded-sm border border-destructive/40 bg-destructive/10 px-3 py-2\">\n <ShieldAlert className=\"mt-0.5 h-3.5 w-3.5 flex-shrink-0 text-destructive\" />\n <p className=\"text-xs leading-relaxed text-destructive\">\n {quality.gateError}\n </p>\n </div>\n )}\n\n {/* A failed analysis is reported in a neutral tone, and the findings\n below it are the previous ones — stale, but the only true thing left\n on screen. */}\n {quality.analysisError && (\n <div className=\"flex items-start gap-2 rounded-sm border bg-muted/60 px-3 py-2\">\n <Info className=\"mt-0.5 h-3.5 w-3.5 flex-shrink-0 text-muted-foreground\" />\n <p className=\"text-xs leading-relaxed text-muted-foreground\">\n {quality.analysisError}\n {findings.length > 0 && ' Showing the last completed analysis.'}\n </p>\n </div>\n )}\n\n <div className=\"space-y-1.5\">\n {quality.truncated && (\n <p className=\"px-0.5 text-[11px] text-muted-foreground/80\">\n The analysis stopped early — not every finding is listed.\n </p>\n )}\n\n {/* A finding the author cannot discover is worse than one they choose\n to ignore, so the filter always says what it swallowed. */}\n {hiddenTotal > 0 && (\n <div className=\"flex items-center gap-2 rounded-sm border border-dashed px-3 py-1.5\">\n <span className=\"min-w-0 flex-1 truncate text-[11px] text-muted-foreground\">\n {showAllSeverities\n ? `${hiddenLabel} below the ${threshold} filter, now shown`\n : `${hiddenLabel} hidden by the ${threshold}-and-above filter`}\n </span>\n <button\n type=\"button\"\n onClick={() => setShowAllSeverities(!showAllSeverities)}\n className={cn(\n 'flex-shrink-0 rounded-sm px-1.5 py-0.5 text-[11px] font-medium',\n 'text-foreground transition-colors hover:bg-accent',\n 'focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-none'\n )}\n >\n {showAllSeverities ? 'Hide again' : 'Show all'}\n </button>\n </div>\n )}\n\n {cappedGroups.map((group) => (\n <div key={group.category} className=\"space-y-1.5\">\n <div className=\"px-0.5 text-[10px] font-medium tracking-wide text-muted-foreground/70 uppercase\">\n {group.category}\n </div>\n {group.findings.map((finding) => (\n <FindingRow\n key={finding.id}\n finding={finding}\n onRevealPath={onRevealPath}\n onApplyFixes={onApplyFixes}\n isApplying={applyingFindingId === finding.id}\n />\n ))}\n </div>\n ))}\n\n {visible.length > ROW_CAP && (\n <button\n type=\"button\"\n onClick={() => setShowAllRows(!showAllRows)}\n className={cn(\n 'w-full rounded-sm border border-dashed px-3 py-1.5 text-[11px]',\n 'font-medium text-muted-foreground transition-colors',\n 'hover:bg-accent hover:text-foreground',\n 'focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-none'\n )}\n >\n {showAllRows\n ? `Show first ${ROW_CAP}`\n : `Show all ${visible.length}`}\n </button>\n )}\n </div>\n </div>\n );\n}\n\n/**\n * True when there is something for the drawer to show.\n *\n * A clean document has a verdict but no detail, so its summary row is a\n * statement rather than a control — offering an empty drawer would be a\n * promise the panel cannot keep.\n */\nexport function hasQualityDetail(\n quality: QualityState | null | undefined\n): boolean {\n if (!quality) return false;\n return (\n quality.findings.length > 0 ||\n Boolean(quality.gateError) ||\n Boolean(quality.analysisError) ||\n Boolean(quality.truncated)\n );\n}\n\nexport interface QualitySummaryProps {\n quality: QualityState | null | undefined;\n /** Whether the findings drawer is open. */\n open?: boolean;\n onToggle?: () => void;\n /** Id of the drawer, for `aria-controls` while it is open. */\n controlsId?: string;\n className?: string;\n}\n\n/**\n * The one-line verdict, sized to sit in a toolbar row.\n *\n * It carries the whole summary — counts by severity, the gate's blocked badge,\n * the profile that ran — so an author never has to open anything to learn\n * where the document stands. The detail is a drawer away.\n */\nexport function QualitySummary({\n quality,\n open = false,\n onToggle,\n controlsId,\n className,\n}: QualitySummaryProps): React.JSX.Element | null {\n const counts = React.useMemo(\n () => countBySeverity(quality?.findings ?? EMPTY_FINDINGS),\n [quality?.findings]\n );\n\n if (!quality) return null;\n\n const isRejected = Boolean(quality.blocked || quality.gateError);\n const chips = SEVERITY_ORDER.filter((severity) => counts[severity] > 0);\n const expandable = hasQualityDetail(quality) && Boolean(onToggle);\n\n const tone = isRejected\n ? 'text-destructive'\n : counts.error > 0\n ? 'text-destructive'\n : counts.warning > 0\n ? 'text-warning'\n : quality.analysisError\n ? 'text-muted-foreground'\n : chips.length === 0\n ? 'text-success'\n : 'text-data-blue';\n const Icon = isRejected\n ? ShieldAlert\n : counts.error > 0\n ? XCircle\n : counts.warning > 0\n ? AlertTriangle\n : quality.analysisError\n ? Info\n : chips.length === 0\n ? CheckCircle2\n : Info;\n\n const content = (\n <>\n {expandable && (\n <ChevronRight\n className={cn(\n 'h-3.5 w-3.5 flex-shrink-0 text-muted-foreground transition-transform',\n open && 'rotate-90'\n )}\n aria-hidden=\"true\"\n />\n )}\n <Icon className={cn('h-3.5 w-3.5 flex-shrink-0', tone)} />\n <span className=\"text-xs font-medium text-foreground\">Quality</span>\n {chips.length === 0 ? (\n <span className=\"truncate text-xs text-muted-foreground\">\n {quality.analysisError ? 'Not available' : 'No findings'}\n </span>\n ) : (\n chips.map((severity, index) => (\n <React.Fragment key={severity}>\n {index > 0 && (\n <span aria-hidden=\"true\" className=\"text-muted-foreground/40\">\n ·\n </span>\n )}\n <span\n className={cn('text-xs font-medium', SEVERITY_TEXT[severity])}\n >\n {countLabel(severity, counts[severity])}\n </span>\n </React.Fragment>\n ))\n )}\n {isRejected && (\n <span className=\"flex-shrink-0 rounded-sm bg-destructive/15 px-1.5 py-0.5 text-[10px] font-medium tracking-wide text-destructive uppercase\">\n blocked\n </span>\n )}\n {quality.profileId && (\n <span\n className=\"ml-auto truncate pl-2 font-mono text-[10px] text-muted-foreground\"\n title={`Quality profile: ${quality.profileId}`}\n >\n {quality.profileId}\n </span>\n )}\n </>\n );\n\n const shared = 'flex min-w-0 items-center gap-2 rounded-sm px-1.5 py-0.5';\n\n // A clean verdict is not a control: there is nothing behind it to open.\n if (!expandable) {\n return <div className={cn(shared, className)}>{content}</div>;\n }\n\n return (\n <button\n type=\"button\"\n onClick={onToggle}\n aria-expanded={open}\n aria-controls={open ? controlsId : undefined}\n className={cn(\n shared,\n 'text-left transition-colors hover:bg-accent',\n 'focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-none',\n className\n )}\n >\n {content}\n </button>\n );\n}\n","import { useMemo } from 'react';\nimport { AlertTriangle } from 'lucide-react';\nimport { useDocumentsStore } from '../../store/documents-store-provider';\nimport { useThemesStore } from '../../store/themes-store-provider';\nimport { FORMAT } from '../../lib/env';\n\n// Theme names registered in the server-side core packages. Documents may\n// reference these even without a matching customThemes entry.\nconst BUILTIN_THEMES: Record<string, readonly string[]> = {\n pptx: ['default', 'dark', 'minimal', 'consulting', 'vermilion', 'devportal'],\n docx: ['minimal', 'devportal', 'vermilion', 'consulting'],\n};\n\nexport function UnavailableThemeWarning({ className }: { className?: string }) {\n const activeTab = useDocumentsStore((s) => s.activeTab);\n const documentTypes = useDocumentsStore((s) => s.documentTypes);\n const documents = useDocumentsStore((s) => s.documents);\n const customThemes = useThemesStore((s) => s.customThemes);\n\n const missingThemeName = useMemo(() => {\n if (!activeTab) return null;\n if (documentTypes[activeTab] === 'application/json+theme') return null;\n\n const doc = documents.find((d) => d.name === activeTab);\n if (!doc?.text) return null;\n\n let themeName: unknown;\n try {\n themeName = JSON.parse(doc.text)?.props?.theme;\n } catch {\n return null;\n }\n if (typeof themeName !== 'string' || !themeName) return null;\n\n if (BUILTIN_THEMES[FORMAT]?.includes(themeName)) return null;\n\n for (const ct of Object.values(customThemes)) {\n if (ct.valid && ct.name === themeName) return null;\n }\n\n return themeName;\n }, [activeTab, documentTypes, documents, customThemes]);\n\n if (!missingThemeName) return null;\n\n return (\n <div\n className={`flex items-start gap-2 rounded-sm border border-transparent bg-warning/10 px-3 py-2 ${className ?? ''}`}\n >\n <AlertTriangle className=\"h-3.5 w-3.5 mt-0.5 text-warning flex-shrink-0\" />\n <div className=\"flex-1 min-w-0 text-xs leading-relaxed\">\n <span className=\"font-medium text-warning\">\n Theme{' '}\n <code className=\"bg-warning/20 px-1 py-0.5 rounded-sm text-warning\">\n {missingThemeName}\n </code>{' '}\n is not available.\n </span>{' '}\n <span className=\"text-warning/80\">\n Add it as a custom theme or use a built-in theme (\n {BUILTIN_THEMES[FORMAT]?.join(', ')}). The renderer will fall back to\n a default.\n </span>\n </div>\n </div>\n );\n}\n","import React, { useEffect, useMemo } from 'react';\nimport { FORMAT } from '../../lib/env';\nimport {\n getAt,\n resolveColor,\n type ThemeJson,\n} from '../../lib/theme-editor/model';\nimport { ensureGoogleFontLoaded } from '../../lib/font-face-inject';\nimport { useFontCatalog } from './theme-editor-shared';\n\n/**\n * The theme, rendered by the browser: the named styles as type, a table,\n * the chart palette. It answers \"what does this look like\" between edits\n * without a round trip; the real render is one click away in the host.\n *\n * It resolves colours and fonts the way the compilers do - a style's colour\n * may name a token, a docx style names a font role, a pptx one a face - but\n * it is a sketch, not the pipeline. Where a theme leaves something unset it\n * falls back to what the compilers default to.\n */\n\ninterface SpecimenText {\n family: string;\n sizePx: number;\n color: string;\n bold: boolean;\n italic: boolean;\n mono: boolean;\n}\n\ninterface SpecimenModel {\n background: string;\n text: string;\n border: string;\n stripe: string;\n primary: string;\n headerText: string;\n palette: { key: string; hex: string }[];\n title: SpecimenText;\n heading1: SpecimenText;\n heading2: SpecimenText;\n body: SpecimenText;\n caption: SpecimenText;\n families: { role: string; family: string }[];\n}\n\nconst FALLBACK = {\n background: '#FFFFFF',\n text: '#1F2937',\n border: '#D1D5DB',\n primary: '#1F2937',\n};\n\n/** Points to pixels at a reduced scale so a 44pt title fits a 260px card. */\nfunction ptToPx(pt: number): number {\n return Math.min(34, Math.max(11, Math.round(pt * 0.75)));\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | undefined {\n return value && typeof value === 'object' && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : undefined;\n}\n\nfunction asNumber(value: unknown): number | undefined {\n return typeof value === 'number' && Number.isFinite(value)\n ? value\n : undefined;\n}\n\nfunction asString(value: unknown): string | undefined {\n return typeof value === 'string' && value.trim() ? value : undefined;\n}\n\nfunction isBold(style: Record<string, unknown> | undefined): boolean {\n if (!style) return false;\n const weight = asNumber(style.fontWeight);\n if (weight !== undefined) return weight >= 600;\n return style.bold === true;\n}\n\n/** docx: a style names a font role; the role carries family and size. */\nfunction docxText(\n theme: ThemeJson,\n styleName: string,\n defaultRole: string,\n defaultSize: number,\n fallbackColor: string\n): SpecimenText {\n const style = asRecord(getAt(theme, ['styles', styleName]));\n const role = asString(style?.font) ?? defaultRole;\n const font = asRecord(getAt(theme, ['fonts', role]));\n const family = asString(font?.family) ?? 'sans-serif';\n const size = asNumber(style?.size) ?? asNumber(font?.size) ?? defaultSize;\n const color =\n resolveColor(theme, style?.color) ??\n resolveColor(theme, font?.color) ??\n fallbackColor;\n return {\n family,\n sizePx: ptToPx(size),\n color,\n bold: isBold(style) || (style === undefined && isBold(font)),\n italic: style?.italic === true,\n mono: role === 'mono',\n };\n}\n\n/** pptx: fonts are plain family strings; sizes come from defaults. */\nfunction pptxText(\n theme: ThemeJson,\n styleName: string,\n defaultRole: 'heading' | 'body',\n defaultSize: number,\n fallbackColor: string\n): SpecimenText {\n const style = asRecord(getAt(theme, ['styles', styleName]));\n const family =\n asString(style?.fontFace) ??\n asString(getAt(theme, ['fonts', defaultRole])) ??\n 'sans-serif';\n const size =\n asNumber(style?.fontSize) ??\n asNumber(getAt(theme, ['defaults', 'fontSize'])) ??\n defaultSize;\n const color =\n resolveColor(theme, style?.fontColor) ??\n resolveColor(theme, getAt(theme, ['defaults', 'fontColor'])) ??\n fallbackColor;\n return {\n family,\n sizePx: ptToPx(size),\n color,\n bold: isBold(style),\n italic: style?.italic === true,\n mono: false,\n };\n}\n\nconst PALETTE_KEYS = [\n 'primary',\n 'secondary',\n 'accent',\n 'accent4',\n 'accent5',\n 'accent6',\n];\n\nfunction buildModel(theme: ThemeJson): SpecimenModel {\n const colors = asRecord(theme.colors) ?? {};\n const resolve = (key: string) => resolveColor(theme, colors[key]);\n const background = resolve('background') ?? FALLBACK.background;\n const text = resolve('text') ?? FALLBACK.text;\n const border =\n resolve('border') ??\n resolve('background2') ??\n resolve('borderPrimary') ??\n FALLBACK.border;\n const stripe =\n resolve('backgroundSecondary') ?? resolve('background2') ?? background;\n const primary = resolve('primary') ?? FALLBACK.primary;\n const muted =\n resolve('textMuted') ??\n resolve('text2') ??\n resolve('textSecondary') ??\n text;\n\n const palette = PALETTE_KEYS.map((key) => ({\n key,\n hex: resolve(key),\n })).filter((entry): entry is { key: string; hex: string } => !!entry.hex);\n\n const docx = FORMAT === 'docx';\n const title = docx\n ? docxText(theme, 'title', 'heading', 28, primary)\n : pptxText(theme, 'title', 'heading', 40, primary);\n const heading1 = docx\n ? docxText(theme, 'heading1', 'heading', 20, primary)\n : pptxText(theme, 'heading1', 'heading', 32, primary);\n const heading2 = docx\n ? docxText(theme, 'heading2', 'heading', 16, primary)\n : pptxText(theme, 'heading2', 'heading', 24, primary);\n const body = docx\n ? docxText(theme, 'normal', 'body', 11, text)\n : pptxText(theme, 'body', 'body', 16, text);\n // docx has no caption style slot: the muted colour on the body face is\n // what a caption component renders with.\n const caption = docx\n ? { ...body, sizePx: 11, color: muted, bold: false }\n : pptxText(theme, 'caption', 'body', 11, muted);\n\n const families: { role: string; family: string }[] = [];\n const fonts = asRecord(theme.fonts) ?? {};\n for (const role of Object.keys(fonts)) {\n const family = docx\n ? asString(asRecord(fonts[role])?.family)\n : asString(fonts[role]);\n if (family) families.push({ role, family });\n }\n\n return {\n background,\n text,\n border,\n stripe,\n primary,\n headerText: background,\n palette,\n title,\n heading1,\n heading2,\n body,\n caption,\n families,\n };\n}\n\nfunction fontStack(family: string, mono: boolean): string {\n const quoted = `\"${family.replace(/\"/g, '')}\"`;\n return mono\n ? `${quoted}, ui-monospace, \"SF Mono\", Menlo, monospace`\n : `${quoted}, \"Inter Variable\", system-ui, sans-serif`;\n}\n\nfunction Line({\n text,\n children,\n block,\n}: {\n text: SpecimenText;\n children: React.ReactNode;\n block?: boolean;\n}) {\n return (\n <div\n className={block ? 'leading-snug' : 'truncate leading-tight'}\n style={{\n fontFamily: fontStack(text.family, text.mono),\n fontSize: text.sizePx,\n color: text.color,\n fontWeight: text.bold ? 700 : 400,\n fontStyle: text.italic ? 'italic' : 'normal',\n }}\n >\n {children}\n </div>\n );\n}\n\nconst TABLE_ROWS: [string, string, string][] = [\n ['Region', 'Q1', 'Q2'],\n ['North', '1,240', '1,385'],\n ['South', '980', '1,102'],\n];\n\nexport function ThemeSpecimen({ theme }: { theme: ThemeJson }) {\n const model = useMemo(() => buildModel(theme), [theme]);\n const catalog = useFontCatalog();\n\n // Families the OS already has cost a failed stylesheet request each; skip\n // the ones the catalog knows to be safe once it has loaded.\n const familyKey = model.families.map((f) => f.family).join('\\n');\n useEffect(() => {\n const safe = new Set(catalog.safe.map((f) => f.toLowerCase()));\n for (const family of new Set(familyKey.split('\\n'))) {\n if (family && !safe.has(family.toLowerCase())) {\n ensureGoogleFontLoaded(family);\n }\n }\n }, [familyKey, catalog.safe]);\n\n return (\n <div\n aria-label=\"Theme sample\"\n title=\"Approximate: the browser's rendering of the theme. Run sample to see the real output.\"\n className=\"@container overflow-hidden rounded-md border\"\n style={{ background: model.background, color: model.text }}\n >\n <div className=\"grid max-h-[260px] grid-cols-1 gap-x-5 gap-y-3 p-4 @[30rem]:grid-cols-[1.3fr_1fr]\">\n <div className=\"flex min-w-0 flex-col gap-1.5\">\n <Line text={model.title}>Annual report</Line>\n <Line text={model.heading1}>1. Executive summary</Line>\n <Line text={model.heading2}>1.1 Where the year landed</Line>\n <Line text={model.body} block>\n Body text in the theme&apos;s body face, sized as the document sets\n it. A second sentence lets the line spacing and colour read.\n </Line>\n <Line text={model.caption}>\n Figure 1 - a caption in the muted colour\n </Line>\n </div>\n\n <div className=\"flex min-w-0 flex-col justify-between gap-3\">\n <table\n className=\"w-full border-collapse\"\n style={{\n fontFamily: fontStack(model.body.family, false),\n fontSize: Math.max(10, model.body.sizePx - 1),\n }}\n >\n <tbody>\n {TABLE_ROWS.map((row, index) => (\n <tr\n key={row[0]}\n style={{\n background:\n index === 0\n ? model.primary\n : index % 2 === 0\n ? model.stripe\n : 'transparent',\n color: index === 0 ? model.headerText : model.text,\n fontWeight: index === 0 ? 600 : 400,\n }}\n >\n {row.map((cell, cellIndex) => (\n <td\n key={cell}\n className=\"px-2 py-1 leading-tight\"\n style={{\n borderBottom: `1px solid ${model.border}`,\n textAlign: cellIndex === 0 ? 'left' : 'right',\n fontVariantNumeric: 'tabular-nums',\n }}\n >\n {cell}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n\n <div className=\"flex flex-col gap-1.5\">\n <div className=\"flex gap-1.5\" aria-label=\"Chart palette\">\n {model.palette.map((entry) => (\n <span\n key={entry.key}\n title={`${entry.key} ${entry.hex}`}\n className=\"h-5 flex-1 rounded-sm\"\n style={{\n background: entry.hex,\n boxShadow: `inset 0 0 0 1px ${model.border}`,\n }}\n />\n ))}\n {model.palette.length === 0 && (\n <span className=\"text-[11px] opacity-60\">No palette yet</span>\n )}\n </div>\n {model.families.length > 0 && (\n <p className=\"truncate text-[10px] opacity-60\">\n {model.families\n .map((f) => `${f.role}: ${f.family}`)\n .join(' / ')}\n </p>\n )}\n </div>\n </div>\n </div>\n </div>\n );\n}\n\nexport const ThemeSpecimenMemoized = React.memo(ThemeSpecimen);\n","import React, { useCallback, useContext, useMemo } from 'react';\nimport { Play } from 'lucide-react';\nimport { Button } from '../ui/button';\nimport { useToast } from '../ui/use-toast';\nimport { ThemeSpecimenMemoized } from '../theme-editor/theme-specimen';\nimport { useDocumentsStore } from '../../store/documents-store-provider';\nimport {\n ThemesStoreContext,\n useThemesStore,\n} from '../../store/themes-store-provider';\nimport { currentDocumentText } from '../../lib/active-document-text';\nimport { parseTheme } from '../../lib/theme-editor/model';\nimport { getThemeName } from '../../lib/theme-validation';\nimport { FORMAT } from '../../lib/env';\n\n/**\n * The theme sample, over the preview.\n *\n * It floats rather than sitting at the top of the form for the same reason\n * the quality drawers do: it changes on every keystroke, and a card that\n * redraws in flow shoves the field being typed in down the screen. Here it\n * sits beside the real render instead — the approximation and the thing it\n * approximates, one Escape apart.\n */\nexport function ThemeSamplePanel({\n themeDocName,\n onRan,\n}: {\n themeDocName: string;\n /** Called once a real render is on its way, so the drawer can get out of it. */\n onRan: () => void;\n}) {\n const text = useDocumentsStore(\n (s) => s.documents.find((d) => d.name === themeDocName)?.text ?? ''\n );\n const updateTheme = useThemesStore((s) => s.updateTheme);\n const themesStore = useContext(ThemesStoreContext);\n const { toast } = useToast();\n\n const parsed = useMemo(() => parseTheme(text), [text]);\n const themeName = parsed.ok ? getThemeName(parsed.theme) : null;\n\n const runSample = useCallback(() => {\n // The JSON view saves on a debounce; the live editor text is the truth.\n const live = currentDocumentText(themeDocName, text);\n let name: string | null = null;\n try {\n name = getThemeName(JSON.parse(live));\n } catch {}\n if (!name) {\n toast({\n title: 'Theme has no name',\n description: 'Give the theme a \"name\" so a document can refer to it.',\n variant: 'destructive',\n });\n return;\n }\n // The build reads the themes store, so it must hold this text before the\n // event fires, ahead of the debounced update the tab would send. Only\n // when it differs: an unchanged theme written again still gets a new\n // record, and the preview treats that as an edit that outdates it.\n const existing = themesStore?.getState().customThemes[themeDocName];\n if (!existing || existing.content !== live) {\n updateTheme(themeDocName, live);\n }\n window.dispatchEvent(\n new CustomEvent('preview:buildSpecimen', { detail: { themeDocName } })\n );\n onRan();\n }, [onRan, text, themeDocName, themesStore, toast, updateTheme]);\n\n return (\n <div className=\"flex flex-col gap-3\">\n <div className=\"flex flex-wrap items-center justify-between gap-2\">\n <div className=\"flex min-w-0 flex-col\">\n <h3 className=\"text-sm font-medium\">Theme sample</h3>\n <p className=\"text-[11px] leading-snug text-muted-foreground\">\n Approximate — drawn by the browser, not the renderer.\n </p>\n </div>\n <Button\n variant=\"outline\"\n size=\"sm\"\n className=\"h-7 shrink-0 gap-1.5 px-2.5 text-xs\"\n onClick={runSample}\n disabled={!themeName}\n title={\n themeName\n ? `Render a sample ${FORMAT === 'docx' ? 'document' : 'deck'} in \"${themeName}\" through the same pipeline as Run`\n : 'Give the theme a name first'\n }\n >\n <Play className=\"size-3.5\" />\n Run sample\n </Button>\n </div>\n {parsed.ok ? (\n <ThemeSpecimenMemoized theme={parsed.theme} />\n ) : (\n <p className=\"text-xs text-muted-foreground\">\n The theme JSON has an error:{' '}\n <span className=\"text-destructive\">{parsed.error}</span>\n </p>\n )}\n </div>\n );\n}\n\nexport const ThemeSamplePanelMemoized = React.memo(ThemeSamplePanel);\n","import { FORMAT } from './env';\nimport { API_ENDPOINTS } from '../config/api';\n\nexport type RenderPayload = {\n iframeSrc?: string;\n iframeSrcDoc?: string;\n cleanup?: () => void;\n};\n\nasync function renderWithLibreOffice(\n name: string,\n blob: Blob,\n jsonText?: string,\n customThemes?: Record<string, unknown>,\n renderer?: string,\n sourceName?: string\n): Promise<RenderPayload> {\n // When we know the source JSON, hit the from-json endpoint. The server\n // generates + converts in one step and passes resolved fonts directly to\n // the LibreOffice font stager — embedded fonts render correctly in the PDF.\n // Falling back to the upload path is still useful if the JSON is lost or\n // we're previewing an externally-supplied file.\n const useJsonPath = typeof jsonText === 'string' && jsonText.length > 0;\n\n let response: Response;\n if (useJsonPath) {\n let jsonDefinition: unknown;\n try {\n jsonDefinition = JSON.parse(jsonText!);\n } catch (err) {\n throw new Error(`Invalid JSON document: ${(err as Error).message}`);\n }\n const body: Record<string, unknown> = {\n jsonDefinition,\n customThemes: customThemes ?? {},\n // sourceName lets the server resolve relative asset paths against the\n // discovered document's own directory (#142). Names only — the server\n // maps them to paths itself. Callers pass the document's template\n // provenance when they know it; the display name is only the fallback.\n //\n // `renderer` is what keeps the preview honest: the server regenerates\n // the document here, and without it the PDF on screen came from the\n // default backend while the download came from the selected one (#255).\n options: {\n sourceName: sourceName ?? name,\n ...(renderer ? { renderer } : {}),\n },\n };\n response = await fetch(API_ENDPOINTS.preview.libreofficeFromJson, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n });\n } else {\n const formData = new FormData();\n const ext = FORMAT === 'pptx' ? '.pptx' : '.docx';\n formData.append('file', blob, `${name}${ext}`);\n response = await fetch(API_ENDPOINTS.preview.libreoffice, {\n method: 'POST',\n body: formData,\n });\n }\n\n if (!response.ok) {\n let message = `LibreOffice preview failed (${response.status})`;\n try {\n const json = await response.json();\n if (json && typeof json === 'object' && typeof json.error === 'string') {\n message = json.error;\n }\n } catch {}\n throw new Error(message);\n }\n\n const pdfBlob = await response.blob();\n if (!pdfBlob.size) {\n throw new Error('LibreOffice preview returned an empty PDF');\n }\n\n const objectUrl = URL.createObjectURL(pdfBlob);\n return {\n iframeSrc: objectUrl,\n cleanup: () => URL.revokeObjectURL(objectUrl),\n };\n}\n\nexport function cleanupIframe(iframe: HTMLIFrameElement) {\n try {\n if (iframe.contentWindow) {\n iframe.contentWindow.location.replace('about:blank');\n }\n iframe.src = 'about:blank';\n iframe.srcdoc = '';\n if (iframe.parentNode) {\n iframe.parentNode.removeChild(iframe);\n }\n } catch (error) {\n console.warn('Error cleaning up iframe:', error);\n }\n}\n\nexport async function renderDocument(\n name: string,\n blob: Blob,\n jsonText?: string,\n customThemes?: Record<string, unknown>,\n renderer?: string,\n sourceName?: string\n) {\n try {\n if (!blob || blob.size === 0) {\n throw new Error('Invalid or empty document blob');\n }\n\n const payload = await renderWithLibreOffice(\n name,\n blob,\n jsonText,\n customThemes,\n renderer,\n sourceName\n );\n\n return { status: 'success' as const, name, payload };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n return { status: 'error' as const, name, payload: new Error(errorMessage) };\n }\n}\n\n// Keep backward compat exports for pptx code\nexport const renderPptx = (name: string, blob: Blob) =>\n renderDocument(name, blob);\n","import { useCallback } from 'react';\nimport { applyQualityFixes, canApplyFixes } from '../lib/quality-fixes';\nimport type { QualityFinding } from '../lib/quality-findings';\nimport { useDocumentsStore } from '../store/documents-store-provider';\nimport { useEditorRefsStore } from '../store/editor-refs-store';\n\nexport interface ApplyQualityFixOutcome {\n ok: boolean;\n error?: string;\n}\n\n/**\n * Apply a finding's suggested fixes to the document it was computed against.\n *\n * The patch deliberately goes through the documents store rather than\n * `editor.executeEdits`: Monaco collapses long strings into `§jtoc:<id>§`\n * sentinels, so the model text is NOT the document. An RFC 6902 patch computed\n * against the real JSON and written into the model would land on a sentinel and\n * silently destroy whatever value it stood for. Writing the document text back\n * to the store is the established route (see `useMutateActiveDocumentAtPath` in\n * font-picker-dialog.tsx) and lets the editor re-expand the text on its own.\n */\nexport function useApplyQualityFix(): (\n finding: QualityFinding,\n expectedDocumentName: string | undefined\n) => ApplyQualityFixOutcome {\n const activeTab = useDocumentsStore((s) => s.activeTab);\n const documents = useDocumentsStore((s) => s.documents);\n const documentTypes = useDocumentsStore((s) => s.documentTypes);\n const saveDocument = useDocumentsStore((s) => s.saveDocument);\n\n return useCallback(\n (\n finding: QualityFinding,\n expectedDocumentName: string | undefined\n ): ApplyQualityFixOutcome => {\n const fixes = finding.fixes;\n // `canApplyFixes` already rejects an empty list and an unresolvable\n // move/copy, so it is the whole guard rather than one of two.\n if (!fixes || !canApplyFixes(fixes)) {\n return { ok: false, error: 'This finding carries no applicable fix.' };\n }\n if (!activeTab) return { ok: false, error: 'No active file' };\n\n // A tab switch leaves the panel showing the previous document's findings\n // until a new analysis lands. Patching whatever happens to be active\n // would write this finding's pointers into a file no finding described —\n // silently, because `applyQualityFixes` only checks that a path resolves,\n // never that it is the path the defect was found at.\n if (expectedDocumentName && expectedDocumentName !== activeTab) {\n return {\n ok: false,\n error: `This finding belongs to ${expectedDocumentName}, which is no longer the active file.`,\n };\n }\n if (documentTypes[activeTab] !== 'application/json+report') {\n return {\n ok: false,\n error:\n 'Quality fixes apply to a document, not to a theme or a plugin.',\n };\n }\n\n const doc = documents.find((d) => d.name === activeTab);\n if (!doc) return { ok: false, error: 'Active document not found' };\n\n // Monaco saves on a 300ms debounce, so the store text can be one burst of\n // typing out of date. Patching that and writing it back would both drop\n // the keystrokes in flight and lose the patch, because the trailing save\n // fires afterwards with its own pre-patch text. Flushing first collapses\n // both races: the store becomes current, and the pending timer has\n // nothing left to deliver.\n const editorRef = useEditorRefsStore.getState().getEditor(activeTab);\n editorRef?.flushPendingSave?.();\n // Read the live model rather than the store snapshot this callback closed\n // over: the flush above has just made them agree, but the snapshot is the\n // one captured at render time.\n const sourceText = editorRef\n ? editorRef.toStorageValue(editorRef.editor.getValue())\n : doc.text;\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(sourceText);\n } catch (err) {\n return {\n ok: false,\n error: `Active document is not valid JSON: ${(err as Error).message}`,\n };\n }\n\n const result = applyQualityFixes(parsed, fixes);\n if (!result.ok) return { ok: false, error: result.error };\n\n saveDocument(activeTab, JSON.stringify(result.doc, null, 2));\n return { ok: true };\n },\n [activeTab, documentTypes, documents, saveDocument]\n );\n}\n","import * as React from 'react';\nimport * as ProgressPrimitive from '@radix-ui/react-progress';\nimport { cn } from '../../lib/utils';\n\nconst Progress = React.forwardRef<\n React.ElementRef<typeof ProgressPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof ProgressPrimitive.Root>\n>(({ className, value, ...props }, ref) => (\n <ProgressPrimitive.Root\n ref={ref}\n className={cn(\n 'relative h-4 w-full overflow-hidden rounded-full bg-secondary',\n className\n )}\n {...props}\n >\n <ProgressPrimitive.Indicator\n className=\"h-full w-full flex-1 bg-primary transition-all\"\n style={{ transform: `translateX(-${100 - (value || 0)}%)` }}\n />\n </ProgressPrimitive.Root>\n));\nProgress.displayName = ProgressPrimitive.Root.displayName;\n\nexport { Progress };\n","import { useEffect, useState } from 'react';\nimport { Badge } from './ui/badge';\nimport { Progress } from './ui/progress';\nimport { API_ENDPOINTS } from '../config/api';\n\ninterface CacheStats {\n document: {\n hits: number;\n misses: number;\n hitRate: number;\n size: number;\n itemCount: number;\n enabled: boolean;\n };\n rasterizer?: RasterizerCacheData;\n}\n\ninterface RasterizerCacheData {\n diskHits: number;\n diskMisses: number;\n hitRate: number;\n dedupedRequests: number;\n rendered: number;\n failed: number;\n entries: number;\n bytes: number;\n prepass?: {\n documents: number;\n collected: number;\n unique: number;\n };\n}\n\nfunction formatBytes(bytes: number): string {\n if (bytes === 0) return '0 B';\n const k = 1024;\n const sizes = ['B', 'KB', 'MB', 'GB'];\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];\n}\n\nexport function CacheMetrics() {\n const [stats, setStats] = useState<CacheStats | null>(null);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n const controller = new AbortController();\n\n const fetchData = async () => {\n try {\n const response = await fetch(API_ENDPOINTS.cacheStats, {\n signal: controller.signal,\n });\n if (!response.ok) throw new Error('Failed to fetch cache stats');\n const data = await response.json();\n\n if (!controller.signal.aborted) {\n setStats(data.data);\n setError(null);\n }\n } catch (err) {\n if (!controller.signal.aborted) {\n if (err instanceof Error && err.name !== 'AbortError') {\n setError(err.message);\n } else if (!(err instanceof Error) || err.name !== 'AbortError') {\n setError('Failed to load cache stats');\n }\n }\n } finally {\n if (!controller.signal.aborted) setLoading(false);\n }\n };\n\n fetchData();\n const interval = setInterval(fetchData, 5000);\n\n const handleCacheCleared = () => fetchData();\n window.addEventListener('cache:cleared', handleCacheCleared);\n\n return () => {\n controller.abort();\n clearInterval(interval);\n window.removeEventListener('cache:cleared', handleCacheCleared);\n };\n }, []);\n\n if (loading) {\n return (\n <div className=\"flex items-center justify-center p-8\">\n <div className=\"animate-spin rounded-full h-8 w-8 border-b-2 border-primary\" />\n </div>\n );\n }\n\n if (error) {\n return (\n <div className=\"text-destructive p-4\">\n Error loading cache metrics: {error}\n </div>\n );\n }\n\n if (!stats) return null;\n\n const { document: doc } = stats;\n const hitRatePct = doc.hitRate * 100;\n\n return (\n <div className=\"space-y-4\">\n {/* Summary row */}\n <div className=\"flex items-center gap-6 text-sm\">\n <div>\n <span className=\"text-muted-foreground\">Hit Rate</span>{' '}\n <span className=\"font-semibold text-base\">\n {hitRatePct.toFixed(1)}%\n </span>\n <span className=\"text-muted-foreground ml-1\">\n ({doc.hits} hits / {doc.misses} misses)\n </span>\n </div>\n <div>\n <span className=\"text-muted-foreground\">Size</span>{' '}\n <span className=\"font-semibold\">{formatBytes(doc.size)}</span>\n <span className=\"text-muted-foreground ml-1\">\n ({doc.itemCount} items)\n </span>\n </div>\n <Badge variant={doc.enabled ? 'default' : 'secondary'}>\n {doc.enabled ? 'Enabled' : 'Disabled'}\n </Badge>\n </div>\n\n <Progress\n value={hitRatePct}\n className=\"h-2\"\n aria-label=\"Cache hit rate\"\n />\n\n {/* Visual rasterizer caches (disk PNG cache + batch dedupe) */}\n {stats.rasterizer && <RasterizerBreakdown data={stats.rasterizer} />}\n </div>\n );\n}\n\nfunction RasterizerBreakdown({ data }: { data: RasterizerCacheData }) {\n const lookups = data.diskHits + data.diskMisses;\n const activity =\n lookups + data.dedupedRequests + data.rendered + data.entries;\n if (activity === 0) return null;\n\n const hitRatePct = data.hitRate * 100;\n const dedupeSaved = data.prepass\n ? data.prepass.collected - data.prepass.unique\n : data.dedupedRequests;\n\n return (\n <div className=\"space-y-2\">\n <h4 className=\"text-sm font-medium\">Visual Rasterizer</h4>\n <div className=\"px-3 py-1.5 text-sm space-y-1.5\">\n <div className=\"flex items-center justify-between\">\n <span className=\"text-muted-foreground\">Disk cache</span>\n <div className=\"flex items-center gap-2 text-xs text-muted-foreground\">\n <span>\n {lookups > 0 ? `${hitRatePct.toFixed(0)}% hit` : 'no lookups'}\n </span>\n <span>\n ({data.diskHits} hits / {data.diskMisses} misses)\n </span>\n <span>\n {data.entries} PNGs, {formatBytes(data.bytes)}\n </span>\n </div>\n </div>\n <Progress\n value={hitRatePct}\n className=\"h-1.5\"\n aria-label=\"Rasterizer disk cache hit rate\"\n />\n <div className=\"flex items-center justify-between text-xs text-muted-foreground\">\n <span>\n {data.rendered} rendered\n {data.failed > 0 ? `, ${data.failed} failed` : ''}\n </span>\n <span>\n {dedupeSaved} duplicate visual{dedupeSaved === 1 ? '' : 's'} deduped\n {data.prepass\n ? ` (${data.prepass.collected} collected → ${data.prepass.unique} unique)`\n : ''}\n </span>\n </div>\n </div>\n </div>\n );\n}\n","import React, {\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { Palette, SlidersHorizontal } from 'lucide-react';\nimport { PreviewFrameMemoized } from './preview-frame';\nimport { PreviewHeaderMemoized } from './preview-header';\nimport { WarningsPanel } from './warnings-panel';\nimport { QualityControls } from './quality-controls';\nimport {\n hasQualityDetail,\n QualityFindings,\n QualitySummary,\n} from './quality-panel';\nimport { UnavailableThemeWarning } from './unavailable-theme-warning';\nimport { ThemeSamplePanelMemoized } from './theme-sample-panel';\nimport { Dialog, DialogContent, DialogHeader, DialogTitle } from '../ui/dialog';\nimport { Separator } from '../ui/separator';\nimport { useToast } from '../ui/use-toast';\nimport { useOutputStore } from '../../store/output-store-provider';\nimport { useSettingsStore } from '../../store/settings-store-provider';\nimport { renderDocument } from '../../lib/render';\nimport {\n DocumentsStoreContext,\n useDocumentsStore,\n useResolveSourceName,\n} from '../../store/documents-store-provider';\nimport { useEditorRefsStore } from '../../store/editor-refs-store';\nimport { useThemesStore } from '../../store/themes-store-provider';\nimport { useApplyQualityFix } from '../../hooks/useApplyQualityFix';\nimport { useQualityAnalysis } from '../../hooks/useQualityAnalysis';\nimport { findPointerRange } from '../../lib/json-pointer';\nimport {\n splitQualityWarnings,\n type QualityFinding,\n} from '../../lib/quality-findings';\nimport { cn } from '../../lib/utils';\nimport { CacheMetrics } from '../cache-metrics';\nimport { FORMAT_LABEL } from '../../lib/env';\n\nexport function Preview() {\n const {\n name,\n text,\n blob,\n renderer,\n isGenerating,\n generationProgress,\n generationStartedAt,\n cancelGeneration,\n globalError,\n cacheStatus,\n cacheHitRate,\n warnings,\n quality,\n isRendering,\n isPreviewStale,\n editSequence,\n lastBuiltSequence,\n setOutput,\n } = useOutputStore((state) => state);\n // Editor text for \"Copy standard components\" — exists before the first Run,\n // unlike the output store's `text` (#155). Themes have no expansion.\n const editorDocumentText = useDocumentsStore((s) =>\n s.activeTab &&\n (s.documentTypes[s.activeTab] ?? 'application/json+report') ===\n 'application/json+report'\n ? s.documents.find((d) => d.name === s.activeTab)?.text\n : undefined\n );\n // Same condition as the text above, so the name and the JSON sent with it\n // always describe one document — the output store's `name` trails a tab\n // switch and is a placeholder before the first Run.\n const editorDocumentName = useDocumentsStore((s) =>\n s.activeTab &&\n (s.documentTypes[s.activeTab] ?? 'application/json+report') ===\n 'application/json+report'\n ? s.activeTab\n : undefined\n );\n const documentsStore = useContext(DocumentsStoreContext)!;\n const { toast } = useToast();\n const applyQualityFix = useApplyQualityFix();\n const { analyze: analyzeQuality } = useQualityAnalysis();\n const [applyingFindingId, setApplyingFindingId] = useState<string | null>(\n null\n );\n const [showQualityControls, setShowQualityControls] = useState(false);\n const [showQualityFindings, setShowQualityFindings] = useState(false);\n const [showThemeSample, setShowThemeSample] = useState(false);\n const qualityDrawerId = React.useId();\n const activeTab = useDocumentsStore((s) => s.activeTab);\n // The theme tab on screen, or '' — the sample is that file's, so it has to\n // close when the author moves to a document that has no sample to draw.\n const activeThemeName = useDocumentsStore((s) =>\n s.activeTab && s.documentTypes[s.activeTab] === 'application/json+theme'\n ? s.activeTab\n : ''\n );\n\n // Findings address one document by JSON Pointer. A tab switch outruns the\n // analysis that follows it, so anything computed against another file is\n // withheld rather than shown over the file now on screen — its paths would\n // reveal the wrong nodes and its patches would edit the wrong document.\n const activeQuality = useMemo(\n () => (quality && quality.documentName === activeTab ? quality : null),\n [quality, activeTab]\n );\n\n const anyDrawerOpen =\n showQualityControls || showQualityFindings || showThemeSample;\n const closeDrawers = useCallback(() => {\n setShowQualityControls(false);\n setShowQualityFindings(false);\n setShowThemeSample(false);\n }, []);\n\n useEffect(() => {\n if (!activeThemeName) setShowThemeSample(false);\n }, [activeThemeName]);\n\n // Escape is what a reader reaches for when something is covering the page.\n useEffect(() => {\n if (!anyDrawerOpen) return;\n const onKey = (event: KeyboardEvent) => {\n if (event.key === 'Escape') closeDrawers();\n };\n window.addEventListener('keydown', onKey);\n return () => window.removeEventListener('keydown', onKey);\n }, [anyDrawerOpen, closeDrawers]);\n\n // A gate the author asked for has refused their build; the reason is the\n // whole point of having asked, so it opens itself rather than waiting to be\n // found behind a summary row.\n const gateError = activeQuality?.gateError;\n useEffect(() => {\n if (gateError) setShowQualityFindings(true);\n }, [gateError]);\n\n // Close the findings drawer once there is nothing left in it — a document\n // that switched away, or one whose last finding was just fixed. Leaving it\n // open would hold an empty card over the page.\n const qualityHasDetail = hasQualityDetail(activeQuality);\n useEffect(() => {\n if (!qualityHasDetail) setShowQualityFindings(false);\n }, [qualityHasDetail]);\n\n // Quality findings ride in on the same `warnings` array as component\n // warnings; only the non-quality ones belong in the warnings bar. The\n // generate path already splits them, so this is the safety net for a\n // warnings list written by anything that does not.\n const otherWarnings = useMemo(\n () => splitQualityWarnings(warnings).others,\n [warnings]\n );\n\n // Jump to the finding's node in whichever editor is focused. The pointer is\n // resolved against the MODEL text, never `toStorageValue`: collapsed\n // long-string sentinels are ordinary JSON strings in the model, so model\n // offsets are the ones that match what is on screen.\n const revealPath = useCallback((path: string) => {\n // An empty pointer addresses the document root, which is never what a\n // malformed finding meant.\n if (!path) return;\n const editorRef = useEditorRefsStore.getState().getActiveEditor();\n if (!editorRef) return;\n const { editor, monaco } = editorRef;\n const model = editor.getModel();\n if (!model) return;\n const found = findPointerRange(model.getValue(), path);\n // An unresolvable pointer scrolls nowhere: jumping to offset 0 would look\n // like the finding pointed at the top of the file.\n if (!found) return;\n const start = model.getPositionAt(found.start);\n const end = model.getPositionAt(found.end);\n const range = new monaco.Range(\n start.lineNumber,\n start.column,\n end.lineNumber,\n end.column\n );\n editor.revealRangeNearTopIfOutsideViewport(\n range,\n monaco.editor.ScrollType.Smooth\n );\n editor.setPosition(start);\n editor.setSelection(range);\n editor.focus();\n }, []);\n\n // Applying is synchronous, so `applyingFindingId` never survives a render and\n // cannot disable the button. Without a lock a double-click applies the same\n // patch twice — and a second `remove` on the same array index deletes the\n // element that shifted into it. Ids clear when the next analysis replaces the\n // list, which is the point at which re-applying would mean something again.\n const appliedFindingIdsRef = useRef<Set<string>>(new Set());\n useEffect(() => {\n appliedFindingIdsRef.current = new Set();\n }, [quality?.seq]);\n\n const handleApplyFixes = useCallback(\n (finding: QualityFinding) => {\n if (appliedFindingIdsRef.current.has(finding.id)) return;\n appliedFindingIdsRef.current.add(finding.id);\n setApplyingFindingId(finding.id);\n try {\n const result = applyQualityFix(finding, quality?.documentName);\n if (!result.ok) {\n appliedFindingIdsRef.current.delete(finding.id);\n toast({\n variant: 'destructive',\n title: 'Could not apply fix',\n description: result.error,\n });\n return;\n }\n // Re-read rather than reusing the text the fix was computed from: the\n // panel must describe the repaired document, and the stale text would\n // reinstate the finding that was just fixed.\n const { activeTab: tab, documents } = documentsStore.getState();\n const repaired = documents.find((d) => d.name === tab)?.text;\n if (repaired) analyzeQuality(tab, repaired, { immediate: true });\n } finally {\n setApplyingFindingId(null);\n }\n },\n [\n analyzeQuality,\n applyQualityFix,\n documentsStore,\n quality?.documentName,\n toast,\n ]\n );\n // Select the raw map (stable reference until themes mutate), then memoize\n // the transform. A selector that returns a freshly-constructed object on\n // every call would burn through Zustand's Object.is equality and retrigger\n // renders indefinitely.\n const customThemesMap = useThemesStore((state) => state.customThemes);\n const themesForServer = useMemo(() => {\n const out: Record<string, unknown> = {};\n for (const ct of Object.values(customThemesMap)) {\n if (ct.valid && ct.name && ct.parsed) out[ct.name] = ct.parsed;\n }\n return out;\n }, [customThemesMap]);\n\n const [iframeSrc, setIframeSrc] = useState<string | undefined>(undefined);\n const [iframeSrcDoc, setIframeSrcDoc] = useState<string | undefined>(\n undefined\n );\n const [showCacheMetrics, setShowCacheMetrics] = useState<boolean>(false);\n const iframeRef = React.useRef<HTMLIFrameElement>(null);\n\n const renderCleanupRef = useRef<(() => void) | null>(null);\n const pendingManualRenderRef = useRef(false);\n const resolveSourceName = useResolveSourceName();\n\n const cleanupRenderedPreview = useCallback(() => {\n if (renderCleanupRef.current) {\n renderCleanupRef.current();\n renderCleanupRef.current = null;\n }\n }, []);\n\n // Core render function\n const doRender = useCallback(\n async (\n docName: string,\n docBlob: Blob,\n docText?: string,\n themes?: Record<string, unknown>,\n renderer?: string\n ) => {\n setOutput({\n isRendering: true,\n isPreviewStale: false,\n globalError: undefined,\n });\n\n try {\n const { status, payload } = await renderDocument(\n docName,\n docBlob,\n docText,\n themes,\n renderer,\n resolveSourceName(docName)\n );\n\n if (status !== 'success') {\n throw payload instanceof Error ? payload : new Error(String(payload));\n }\n\n cleanupRenderedPreview();\n setIframeSrc(payload.iframeSrc || undefined);\n setIframeSrcDoc(payload.iframeSrcDoc || undefined);\n renderCleanupRef.current = payload.cleanup || null;\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n\n let displayMessage = errorMessage;\n if (errorMessage.includes('Failed to fetch')) {\n displayMessage =\n 'Network error: Unable to load required resources. Check if the server is running properly.';\n } else if (errorMessage.includes('timeout')) {\n displayMessage =\n 'Render timeout: The rendering process took too long.';\n }\n\n setOutput({ globalError: displayMessage });\n } finally {\n setOutput({ isRendering: false });\n }\n },\n [setOutput, cleanupRenderedPreview, resolveSourceName]\n );\n\n // Ref to always hold latest manual-render deps so the event listener never goes stale\n const manualRenderRef = useRef({ name, blob, text, doRender });\n useEffect(() => {\n manualRenderRef.current = { name, blob, text, doRender };\n });\n\n const handleManualRender = useCallback(async () => {\n // Set flag so blob-change effect renders the new blob when it arrives\n pendingManualRenderRef.current = true;\n // Flush debounces + trigger build via editor.tsx\n window.dispatchEvent(new CustomEvent('preview:flushAndBuild'));\n }, []); // stable — reads from ref\n\n // A new blob renders only when a Run asked for it. Converting through\n // LibreOffice costs a round trip, so an edit marks the preview stale and\n // waits rather than rebuilding under the author.\n useEffect(() => {\n if (!blob || !name) return;\n if (pendingManualRenderRef.current) {\n pendingManualRenderRef.current = false;\n // Use the backend captured with this blob, never the live picker: the\n // selection may have changed while generation was in flight (#255).\n doRender(name, blob, text, themesForServer, renderer);\n return;\n }\n setOutput({ isPreviewStale: true });\n }, [blob, name, text, themesForServer, renderer, doRender, setOutput]);\n\n // Cleanup on unmount\n useEffect(() => {\n return () => {\n cleanupRenderedPreview();\n };\n }, [cleanupRenderedPreview]);\n\n // Listen for global header events (stable — handleManualRender never changes)\n useEffect(() => {\n const onManual = () => handleManualRender();\n const onShowCache = () => setShowCacheMetrics(true);\n // A theme's specimen is a Run the author asked for from the theme editor:\n // the editor builds it, and the blob must render when it lands rather\n // than sit behind \"Outdated\" like an unrequested rebuild would.\n const onSpecimen = () => {\n pendingManualRenderRef.current = true;\n };\n\n window.addEventListener('preview:manualRender', onManual);\n window.addEventListener('preview:showCacheMetrics', onShowCache);\n window.addEventListener('preview:buildSpecimen', onSpecimen);\n return () => {\n window.removeEventListener('preview:manualRender', onManual);\n window.removeEventListener('preview:showCacheMetrics', onShowCache);\n window.removeEventListener('preview:buildSpecimen', onSpecimen);\n };\n }, [handleManualRender]);\n\n const localHeaderVisible =\n (useSettingsStore as any)?.getState?.().useGlobalPreviewHeader === false;\n\n return (\n <>\n <div className=\"flex h-full flex-col\">\n {localHeaderVisible && (\n <PreviewHeaderMemoized\n name={name?.trim() || 'Preview'}\n blob={blob}\n onManualRender={handleManualRender}\n isGenerating={isGenerating}\n isRendering={isRendering}\n onShowCacheMetrics={() => setShowCacheMetrics(true)}\n documentText={text}\n editorDocumentText={editorDocumentText}\n editorDocumentName={editorDocumentName}\n warnings={warnings}\n />\n )}\n {/* The local header draws its own `border-b`; a standalone separator\n underneath it stacked two hairlines. */}\n {!localHeaderVisible && <Separator />}\n {/* One status strip, not two. Build state and quality state describe\n the same document at the same moment, and stacking them cost two\n hairlines and two rows of height above the page being read.\n Segments carry their own colour instead of the row carrying a\n tint, so a stale build and a failing gate can be shown at once\n without two backgrounds competing. */}\n {(() => {\n const hasUnsyncedEdits =\n (editSequence ?? 0) > (lastBuiltSequence ?? 0);\n const isStale =\n (isPreviewStale || hasUnsyncedEdits) &&\n !isGenerating &&\n !isRendering;\n const buildStatus = isStale ? (\n <>\n <div className=\"h-1.5 w-1.5 flex-shrink-0 rounded-full bg-warning\" />\n <span className=\"truncate text-xs text-warning\">\n Outdated — click Run\n </span>\n </>\n ) : cacheStatus === 'HIT' ? (\n <>\n <div className=\"h-1.5 w-1.5 flex-shrink-0 rounded-full bg-success\" />\n <span className=\"truncate text-xs text-muted-foreground\">\n Cached\n </span>\n </>\n ) : cacheStatus === 'MISS' ? (\n <>\n <div className=\"h-1.5 w-1.5 flex-shrink-0 rounded-full bg-accent2\" />\n <span className=\"truncate text-xs text-muted-foreground\">\n Fresh {FORMAT_LABEL.toLowerCase()}\n </span>\n </>\n ) : null;\n const showBuildStatus =\n Boolean(buildStatus) &&\n ((cacheStatus && cacheStatus !== 'UNKNOWN') || isStale);\n\n return (\n <div className=\"flex items-center gap-2 overflow-hidden border-b bg-header-bg px-3 py-1.5\">\n {showBuildStatus && (\n <div className=\"flex min-w-0 flex-shrink items-center gap-2\">\n {buildStatus}\n </div>\n )}\n {showBuildStatus && activeQuality && (\n <div\n aria-hidden=\"true\"\n className=\"h-3 w-px flex-shrink-0 bg-border\"\n />\n )}\n <QualitySummary\n quality={activeQuality}\n open={showQualityFindings}\n onToggle={() => {\n setShowQualityFindings((open) => !open);\n setShowThemeSample(false);\n }}\n controlsId={qualityDrawerId}\n className=\"min-w-0 flex-1\"\n />\n {/* The hit rate is a diagnostic, so it is the first thing to go\n when the row runs out of width; the full figures live in the\n cache dialog. */}\n {!isStale && cacheHitRate && cacheHitRate !== '0.0%' && (\n <span className=\"hidden flex-shrink-0 text-xs text-muted-foreground lg:inline\">\n {cacheHitRate} hit rate\n </span>\n )}\n {activeThemeName && (\n <button\n type=\"button\"\n onClick={() => {\n setShowThemeSample((open) => !open);\n setShowQualityControls(false);\n setShowQualityFindings(false);\n }}\n aria-expanded={showThemeSample}\n // The label is hidden below `sm`; the icon is decorative.\n aria-label=\"Theme sample\"\n className={cn(\n 'flex flex-shrink-0 items-center gap-1.5 rounded-sm px-1.5 py-0.5',\n 'text-[11px] font-medium transition-colors',\n 'focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-none',\n showThemeSample\n ? 'bg-accent text-foreground'\n : 'text-muted-foreground hover:bg-accent hover:text-foreground'\n )}\n >\n <Palette className=\"h-3 w-3\" aria-hidden=\"true\" />\n <span className=\"hidden sm:inline\">Theme sample</span>\n </button>\n )}\n <button\n type=\"button\"\n onClick={() => {\n setShowQualityControls(!showQualityControls);\n setShowThemeSample(false);\n }}\n aria-expanded={showQualityControls}\n aria-label=\"Quality settings\"\n className={cn(\n 'flex flex-shrink-0 items-center gap-1.5 rounded-sm px-1.5 py-0.5',\n 'text-[11px] font-medium text-muted-foreground',\n 'transition-colors hover:bg-accent hover:text-foreground',\n 'focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-none'\n )}\n >\n <SlidersHorizontal className=\"h-3 w-3\" aria-hidden=\"true\" />\n <span className=\"hidden sm:inline\">Quality settings</span>\n </button>\n </div>\n );\n })()}\n {/* Warnings Panel */}\n <WarningsPanel warnings={otherWarnings} className=\"mx-3 my-2\" />\n <UnavailableThemeWarning className=\"mx-3 my-2\" />\n {/* The drawers float over this region rather than sitting above it in\n the column. Quality re-analyses on every pause in typing, and a\n panel in flow would shove the page the author is reading down the\n screen each time a finding appeared or cleared. */}\n <div className=\"relative min-h-0 flex-1\">\n {/* Generation Error — centered in preview area */}\n {globalError && !isGenerating ? (\n <div className=\"flex h-full items-center justify-center p-6\">\n <div className=\"max-w-md rounded-sm border-l-4 border-l-destructive bg-destructive/10 px-4 py-3 text-sm text-destructive\">\n <p className=\"font-medium mb-1\">Generation failed</p>\n <p className=\"text-xs text-destructive/80 break-words\">\n {globalError}\n </p>\n </div>\n </div>\n ) : (\n <PreviewFrameMemoized\n ref={iframeRef}\n isLoading={Boolean(isRendering)}\n iframeSrc={iframeSrc}\n iframeSrcDoc={iframeSrcDoc}\n isGenerating={Boolean(isGenerating)}\n generationProgress={generationProgress}\n generationDocumentText={editorDocumentText ?? text}\n generationStartedAt={generationStartedAt}\n onCancelGeneration={cancelGeneration}\n />\n )}\n\n {anyDrawerOpen && (\n <>\n {/* Catches the click that dismisses. Transparent, so the page\n stays legible behind an open drawer. */}\n <div\n className=\"absolute inset-0 z-30\"\n onClick={closeDrawers}\n aria-hidden=\"true\"\n />\n <div\n className={cn(\n 'absolute inset-x-3 top-2 z-40 overflow-y-auto',\n 'rounded-sm border bg-card p-4 shadow-lg',\n // A findings list is as long as the document is bad, so it\n // is pinned top and bottom and scrolls inside the whole\n // pane rather than looking like a tooltip that ran out of\n // room. The sample is one fixed card: pinning it would\n // leave most of the drawer empty, so it takes its own\n // height and only caps at the pane.\n showThemeSample &&\n !showQualityControls &&\n !showQualityFindings\n ? 'max-h-[calc(100%-1rem)]'\n : 'bottom-2'\n )}\n >\n {showThemeSample && activeThemeName && (\n <ThemeSamplePanelMemoized\n themeDocName={activeThemeName}\n onRan={closeDrawers}\n />\n )}\n {showQualityControls && <QualityControls />}\n {showQualityControls && showQualityFindings && (\n <div className=\"my-4 border-t\" />\n )}\n {showQualityFindings && (\n <QualityFindings\n id={qualityDrawerId}\n quality={activeQuality}\n onRevealPath={revealPath}\n onApplyFixes={handleApplyFixes}\n applyingFindingId={applyingFindingId}\n />\n )}\n </div>\n </>\n )}\n </div>\n </div>\n\n {/* Cache Metrics Dialog */}\n <Dialog open={showCacheMetrics} onOpenChange={setShowCacheMetrics}>\n <DialogContent className=\"max-w-2xl\">\n <DialogHeader>\n <DialogTitle>Cache Performance</DialogTitle>\n </DialogHeader>\n <CacheMetrics />\n </DialogContent>\n </Dialog>\n </>\n );\n}\n"],"names":["useElapsedSeconds","startedAt","fallbackStart","useState","start","now","setNow","useEffect","id","summarizeDocument","text","root","counts","stack","node","name","children","summary","key","singular","plural","count","entry","title","_b","_a","buildHints","hints","CheckIcon","jsx","DocumentGenerationLoader","className","currentStage","message","documentText","onCancel","stages","stageLabels","currentStageIndex","elapsed","useMemo","showHints","hintIndex","cn","jsxs","Spinner","label","stage","index","isActive","isCompleted","Button","GenerationOverlay","mode","PreviewLoading","renderingLibrary","getLibraryInfo","library","description","Skeleton","PreviewFrame","React","isLoading","iframeSrc","iframeSrcDoc","isGenerating","generationProgress","generationDocumentText","generationStartedAt","onCancelGeneration","ref","iframeLoaded","setIframeLoaded","handleIframeLoad","handleIframeError","iframeSandbox","hasContent","FORMAT_LABEL","PreviewFrameMemoized","WarningsPanel","warnings","isExpanded","setIsExpanded","reportable","w","ChevronRight","AlertTriangle","warning","Info","QualityPolicyEditor","resolvedTheme","useTheme","policies","useSettingsStore","s","setSettings","stored","FORMAT","setText","EMPTY_POLICY_TEXT","parsed","parseQualityPolicy","ruleIds","rulesForFormat","rule","commit","useCallback","next","editorRef","useRef","reset","instance","RotateCcw","Editor","QUALITY_POLICY_MODEL_PATH","value","DEFAULT_PROFILE_VALUE","PROFILES","DEFAULT_PROFILE_ID","GATES","MIN_SEVERITIES","TRIGGER_CLASS","CONTENT_CLASS","LABEL_CLASS","HELP_CLASS","DEFAULT_PROFILE_CHOICE","SectionHeading","ChoiceRow","choice","QualityControls","fieldId","useId","profileIds","profileId","gate","minSeverity","profiles","selectedProfile","selectedGate","selectedSeverity","Label","SlidersHorizontal","Select","SelectTrigger","SelectValue","SelectContent","SelectItem","ShieldAlert","Eye","ARRAY_INDEX_RE","decodePointerSegment","segment","encodePointerSegment","pointerToPathArray","pointer","raw","decoded","pathArrayToPointer","path","resolveSegment","hit","findNodeAtLocation","findPointerRange","parseTree","SUPPORTED_OPS","applyQualityFixes","doc","fixes","outcome","applyOne","error","describeError","canApplyFixes","fix","isSupportedOp","op","fail","addAtPath","replaceAtPath","removed","removeAtPath","step","from","readFrom","source","resolvePath","samePath","isProperPrefix","describePointer","actual","deepEqual","last","updateParent","parent","toIndex","cloneContainer","isPlainObject","hasOwn","clone","update","rewrite","parentPath","depth","here","child","current","a","b","seg","i","prefix","item","keys","ROW_CAP","EMPTY_FINDINGS","SEVERITY_ORDER","SEVERITY_ICONS","XCircle","SEVERITY_TEXT","EVIDENCE_SUMMARY_KEYS","countLabel","severity","formatEvidenceValue","unit","base","extraEvidence","evidence","rest","found","PathChip","onRevealPath","muted","Crosshair","FindingRow","finding","onApplyFixes","isApplying","Icon","tone","certainty","certaintyLabel","hasComparison","showFix","relatedPaths","Fragment","Wand2","related","QualityFindings","quality","applyingFindingId","state","showAllSeverities","setShowAllSeverities","showAllRows","setShowAllRows","findings","threshold","kept","filterByMinSeverity","visible","groups","groupByCategory","cappedGroups","budget","out","group","slice","countBySeverity","keptCounts","hiddenTotal","hiddenLabel","parts","named","n","hasQualityDetail","QualitySummary","open","onToggle","controlsId","isRejected","chips","expandable","CheckCircle2","content","shared","BUILTIN_THEMES","UnavailableThemeWarning","activeTab","useDocumentsStore","documentTypes","documents","customThemes","useThemesStore","missingThemeName","d","themeName","_c","ct","FALLBACK","ptToPx","pt","asRecord","asNumber","asString","isBold","style","weight","docxText","theme","styleName","defaultRole","defaultSize","fallbackColor","getAt","role","font","family","size","color","resolveColor","pptxText","PALETTE_KEYS","buildModel","colors","resolve","background","border","stripe","primary","palette","docx","heading1","heading2","body","caption","families","fonts","fontStack","mono","quoted","Line","block","TABLE_ROWS","ThemeSpecimen","model","catalog","useFontCatalog","familyKey","f","safe","ensureGoogleFontLoaded","row","cell","cellIndex","ThemeSpecimenMemoized","ThemeSamplePanel","themeDocName","onRan","updateTheme","themesStore","useContext","ThemesStoreContext","toast","useToast","parseTheme","getThemeName","runSample","live","currentDocumentText","existing","Play","ThemeSamplePanelMemoized","renderWithLibreOffice","blob","jsonText","renderer","sourceName","useJsonPath","response","jsonDefinition","err","API_ENDPOINTS","formData","ext","json","pdfBlob","objectUrl","renderDocument","payload","errorMessage","useApplyQualityFix","saveDocument","expectedDocumentName","useEditorRefsStore","sourceText","result","Progress","React.forwardRef","props","ProgressPrimitive.Root","ProgressPrimitive.Indicator","formatBytes","bytes","k","sizes","CacheMetrics","stats","setStats","loading","setLoading","setError","controller","fetchData","data","interval","handleCacheCleared","hitRatePct","Badge","RasterizerBreakdown","lookups","dedupeSaved","Preview","cancelGeneration","globalError","cacheStatus","cacheHitRate","isRendering","isPreviewStale","editSequence","lastBuiltSequence","setOutput","useOutputStore","editorDocumentText","editorDocumentName","documentsStore","DocumentsStoreContext","applyQualityFix","analyzeQuality","useQualityAnalysis","setApplyingFindingId","showQualityControls","setShowQualityControls","showQualityFindings","setShowQualityFindings","showThemeSample","setShowThemeSample","qualityDrawerId","activeThemeName","activeQuality","anyDrawerOpen","closeDrawers","onKey","event","gateError","qualityHasDetail","otherWarnings","splitQualityWarnings","revealPath","editor","monaco","end","range","appliedFindingIdsRef","handleApplyFixes","tab","repaired","customThemesMap","themesForServer","setIframeSrc","setIframeSrcDoc","showCacheMetrics","setShowCacheMetrics","iframeRef","renderCleanupRef","pendingManualRenderRef","resolveSourceName","useResolveSourceName","cleanupRenderedPreview","doRender","docName","docBlob","docText","themes","status","displayMessage","manualRenderRef","handleManualRender","onManual","onShowCache","onSpecimen","localHeaderVisible","PreviewHeaderMemoized","Separator","hasUnsyncedEdits","isStale","buildStatus","showBuildStatus","Palette","Dialog","DialogContent","DialogHeader","DialogTitle"],"mappings":"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"}