{"version":3,"sources":["../src/components/CodeView/CodeView.tsx"],"names":["useSyncExternalStore","useRef","DARK_COLORS","LIGHT_COLORS","useMemo","tokenizeHtml","highlightCode","useEffect","jsx","cn","jsxs"],"mappings":"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","file":"chunk-G7227RTY.cjs","sourcesContent":["import { useEffect, useMemo, useRef, useSyncExternalStore } from \"react\";\nimport {\n  highlightCode,\n  tokenizeHtml,\n  LIGHT_COLORS,\n  DARK_COLORS,\n  type ThemeColors,\n} from \"@particle-academy/fancy-file-commons\";\nimport { cn } from \"../../utils/cn\";\nimport type { CodeViewProps } from \"./CodeView.types\";\n\n// ── Dark-mode detection ────────────────────────────────────────────────────\n// The highlight palette is baked in as inline colors, so we resolve light/dark\n// ourselves. Follow BOTH signals so we match whatever drives the surrounding\n// `dark:` Tailwind variants: the `.dark` class (class strategy) OR the\n// prefers-color-scheme media query (media strategy).\n\nfunction subscribeDark(callback: () => void): () => void {\n  const mq = window.matchMedia(\"(prefers-color-scheme: dark)\");\n  mq.addEventListener(\"change\", callback);\n  const observer = new MutationObserver(callback);\n  observer.observe(document.documentElement, {\n    attributes: true,\n    attributeFilter: [\"class\"],\n  });\n  return () => {\n    mq.removeEventListener(\"change\", callback);\n    observer.disconnect();\n  };\n}\n\nfunction darkSnapshot(): boolean {\n  return (\n    document.documentElement.classList.contains(\"dark\") ||\n    window.matchMedia(\"(prefers-color-scheme: dark)\").matches\n  );\n}\n\nfunction useIsDark(): boolean {\n  return useSyncExternalStore(subscribeDark, darkSnapshot, () => false);\n}\n\n// Shared text metrics — the overlay and the textarea MUST match exactly (font,\n// size, line-height, padding, wrapping) so the highlighted glyphs sit under the\n// caret. Keep this string identical on both layers.\nconst TEXT_METRICS = \"m-0 p-3 font-mono text-xs leading-relaxed\";\n\n/**\n * A lightweight, syntax-highlighted source view built on the pure highlight\n * primitives in `@particle-academy/fancy-file-commons` — a highlight overlay\n * with a transparent, auto-growing textarea on top; the container scrolls both\n * together. Fills its parent's height (`h-full`) and grows with content down to\n * `minHeight`. Only HTML is highlighted; other languages render as plain text.\n */\nexport function CodeView({\n  value,\n  onChange,\n  language = \"plaintext\",\n  readOnly = false,\n  placeholder,\n  minHeight = 120,\n  maxHeight,\n  className,\n}: CodeViewProps) {\n  const textareaRef = useRef<HTMLTextAreaElement | null>(null);\n  const isDark = useIsDark();\n  const colors: ThemeColors = isDark ? DARK_COLORS : LIGHT_COLORS;\n\n  const highlighted = useMemo(() => {\n    const tokens = language === \"html\" ? tokenizeHtml(value) : [];\n    return highlightCode(value, tokens, colors);\n  }, [value, language, colors]);\n\n  // Grow the textarea to its content height so it never scrolls internally —\n  // the outer container owns scrolling and moves overlay + textarea in lockstep.\n  useEffect(() => {\n    const el = textareaRef.current;\n    if (!el) return;\n    el.style.height = \"auto\";\n    el.style.height = `${el.scrollHeight}px`;\n  }, [value]);\n\n  const editable = !readOnly && !!onChange;\n\n  return (\n    <div\n      data-react-fancy-code-view=\"\"\n      // No baked-in height: the consumer picks the fill mechanism — `flex-1`\n      // inside a flex column (the Editor source body), or `h-full` when the\n      // parent has a definite height. A hard-coded `h-full` here collapses to\n      // content height under a flex-computed (indefinite) parent.\n      className={cn(\"relative overflow-auto\", className)}\n      style={{ backgroundColor: colors.background, color: colors.foreground, minHeight, maxHeight }}\n    >\n      <div className=\"relative min-h-full\">\n        {/* Highlight overlay */}\n        <pre\n          aria-hidden=\"true\"\n          className={cn(\"pointer-events-none absolute inset-0 overflow-hidden border-none\", TEXT_METRICS)}\n          style={{ whiteSpace: \"pre-wrap\", overflowWrap: \"break-word\" }}\n        >\n          <code dangerouslySetInnerHTML={{ __html: highlighted + \"\\n\" }} />\n        </pre>\n\n        {/* Placeholder */}\n        {placeholder && value.length === 0 && (\n          <div className={cn(\"pointer-events-none absolute left-0 top-0 opacity-40\", TEXT_METRICS)}>\n            {placeholder}\n          </div>\n        )}\n\n        {/* Transparent input layer (caret + selection visible, glyphs from overlay) */}\n        <textarea\n          ref={textareaRef}\n          data-react-fancy-code-view-input=\"\"\n          value={value}\n          onChange={editable ? (e) => onChange!(e.target.value) : undefined}\n          readOnly={!editable}\n          spellCheck={false}\n          autoComplete=\"off\"\n          autoCorrect=\"off\"\n          autoCapitalize=\"off\"\n          aria-label={placeholder}\n          className={cn(\n            \"relative block w-full resize-none border-none bg-transparent text-transparent outline-none\",\n            TEXT_METRICS,\n          )}\n          style={{\n            caretColor: colors.cursorColor,\n            overflow: \"hidden\",\n            whiteSpace: \"pre-wrap\",\n            overflowWrap: \"break-word\",\n            minHeight,\n          }}\n        />\n      </div>\n    </div>\n  );\n}\n\nCodeView.displayName = \"CodeView\";\n"]}