{"version":3,"file":"HtmlPreview.mjs","names":["Flexbox"],"sources":["../../src/HtmlPreview/HtmlPreview.tsx"],"sourcesContent":["'use client';\n\nimport { createStyles, cx, keyframes } from 'antd-style';\nimport { Download, Expand } from 'lucide-react';\nimport { memo, type ReactNode, useCallback, useEffect, useMemo, useRef, useState } from 'react';\n\nimport ActionIcon from '@/ActionIcon';\nimport CopyButton from '@/CopyButton';\nimport { Flexbox } from '@/Flex';\nimport { actionsHoverCls, variants } from '@/Highlighter/style';\nimport SyntaxHighlighter from '@/Highlighter/SyntaxHighlighter';\nimport NeuralNetworkLoading from '@/NeuralNetworkLoading';\nimport Segmented from '@/Segmented';\nimport { stopPropagation } from '@/utils/dom';\nimport { downloadBlob } from '@/utils/downloadBlob';\n\nimport { containsScript, DEFAULT_HEIGHT, isFullHtmlDocument, isHtmlContentClosed } from './const';\nimport HtmlPreviewIframe from './Iframe';\nimport type { HtmlPreviewMode, HtmlPreviewProps } from './type';\n\n// Sheen sweep direction: left → right.\n// `background-position` works inversely from \"where the image is drawn\":\n// at `200%` the over-sized gradient starts off to the left of the\n// container, at `-200%` it ends off to the right — so animating\n// 200% → -200% moves the visible bright spot from left to right.\nconst shimmer = keyframes`\n  0%   { background-position: 200% 0; }\n  100% { background-position: -200% 0; }\n`;\n\nconst useStyles = createStyles(({ css, cssVar, isDarkMode }) => ({\n  loadingBackdrop: css`\n    pointer-events: none;\n\n    position: absolute;\n    z-index: 1;\n    inset: 0;\n\n    /* Subtle moving sheen so it doesn't look frozen. */\n    background: linear-gradient(\n      90deg,\n      transparent 0%,\n      ${isDarkMode ? 'rgba(255, 255, 255, 0.04)' : 'rgba(0, 0, 0, 0.04)'} 50%,\n      transparent 100%\n    );\n    background-repeat: no-repeat;\n    background-size: 200% 100%;\n\n    animation: ${shimmer} 1.6s ${cssVar.motionEaseInOut} infinite;\n  `,\n  loadingBadge: css`\n    position: absolute;\n    z-index: 2;\n    inset-block-start: 12px;\n    inset-inline-start: 12px;\n\n    display: inline-flex;\n    gap: 8px;\n    align-items: center;\n\n    padding-block: 4px;\n    padding-inline: 6px 10px;\n    border-radius: 999px;\n\n    font-size: 12px;\n    color: ${cssVar.colorTextDescription};\n\n    background: ${cssVar.colorBgContainer};\n    backdrop-filter: blur(8px);\n    box-shadow: 0 0 0 1px ${cssVar.colorBorderSecondary};\n  `,\n  // The streaming source visible during Phase 1 — heavily faded so it\n  // reads as \"this is preview-pending content\" rather than the finished\n  // article. Auto-follows the tail so the user can see new tokens land\n  // even on slow models.\n  loadingSource: css`\n    pointer-events: none;\n    overflow: hidden;\n    height: 100%;\n\n    /* Faded out so the iframe transition feels like content lighting up,\n       not like one document jump-cutting to another. */\n    opacity: 0.45;\n\n    /* SyntaxHighlighter sets its own background; flatten so the shimmer\n       overlay reads cleanly on top. */\n    & [data-code-type='highlighter'] {\n      background: transparent;\n      box-shadow: none;\n    }\n\n    /* Tail-follow is layout-only — we anchor the scrollable element to\n       its scrollHeight via the ref + effect; CSS just keeps the\n       overflow hidden. */\n    & pre,\n    & code {\n      background: transparent !important;\n    }\n  `,\n  loadingRoot: css`\n    position: relative;\n    overflow: hidden;\n    background: ${isDarkMode ? '#1f1f1f' : '#fafafa'};\n  `,\n  // Inline top-right toolbar. Tagged with `actionsHoverCls` so the Highlighter\n  // container's `&:hover .${actionsHoverCls} { opacity: 1 }` rule flips it\n  // in/out as the user moves over the preview — same UX as the regular code\n  // block actions.\n  toolbar: cx(\n    actionsHoverCls,\n    css`\n      position: absolute;\n      z-index: 2;\n      inset-block-start: 8px;\n      inset-inline-end: 8px;\n\n      padding: 4px;\n      border-radius: ${cssVar.borderRadiusLG};\n\n      opacity: 0;\n      background: ${cssVar.colorBgContainer};\n      backdrop-filter: blur(8px);\n      box-shadow: 0 0 0 1px ${cssVar.colorBorderSecondary};\n\n      transition: opacity 0.2s ${cssVar.motionEaseOut};\n\n      &:focus-within {\n        opacity: 1;\n      }\n    `,\n  ),\n}));\n\nconst themeBackground = (theme?: 'light' | 'dark') => {\n  if (theme === 'dark') return '#1f1f1f';\n  if (theme === 'light') return '#ffffff';\n  return undefined;\n};\n\nconst downloadHtml = async (content: string, fileName: string) => {\n  const blob = new Blob([content], { type: 'text/html;charset=utf-8' });\n  const url = URL.createObjectURL(blob);\n  try {\n    await downloadBlob(url, fileName);\n  } finally {\n    URL.revokeObjectURL(url);\n  }\n};\n\nconst HtmlPreview = memo<HtmlPreviewProps>(\n  ({\n    actionIconSize,\n    actionsRender,\n    animated,\n    bodyRender,\n    children,\n    className,\n    classNames,\n    copyable = true,\n    defaultHeight,\n    defaultMode = 'preview',\n    downloadable = true,\n    fileName,\n    language = 'html',\n    onExpand,\n    sandbox,\n    shadow,\n    streamingMode = 'auto',\n    style,\n    styles: customStyles,\n    theme,\n    variant = 'filled',\n    // `fullFeatured` / `showLanguage` / `defaultExpand` are accepted for API\n    // compatibility with the rest of the Pre family but no longer drive a\n    // separate header — the inline toolbar is always rendered.\n    fullFeatured: _fullFeatured,\n    showLanguage: _showLanguage,\n    defaultExpand: _defaultExpand,\n    ...rest\n  }) => {\n    const trimmedChildren = useMemo(() => (children || '').trim(), [children]);\n    const isFragment = useMemo(() => !isFullHtmlDocument(trimmedChildren), [trimmedChildren]);\n\n    // Per-session tracking. Reset on `animated` edge false → true.\n    const [scriptLocked, setScriptLocked] = useState(false);\n    const [headClosed, setHeadClosed] = useState(false);\n    const [liveCommitted, setLiveCommitted] = useState(false);\n    const prevAnimatedRef = useRef(animated);\n    const lastCommitRef = useRef(0);\n    const pendingTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n    const latestContentRef = useRef(trimmedChildren);\n    useEffect(() => {\n      latestContentRef.current = trimmedChildren;\n    }, [trimmedChildren]);\n    useEffect(() => {\n      if (animated && !prevAnimatedRef.current) {\n        setScriptLocked(false);\n        setHeadClosed(false);\n        setLiveCommitted(false);\n        lastCommitRef.current = 0;\n        if (pendingTimerRef.current) {\n          clearTimeout(pendingTimerRef.current);\n          pendingTimerRef.current = null;\n        }\n      }\n      prevAnimatedRef.current = animated;\n    }, [animated]);\n\n    // Sticky script detection: once a `<script>` appears in this session,\n    // auto mode locks into defer.\n    useEffect(() => {\n      if (animated && !scriptLocked && containsScript(trimmedChildren)) {\n        setScriptLocked(true);\n      }\n    }, [trimmedChildren, animated, scriptLocked]);\n\n    // Track whether the head section has closed. Until it does, the iframe\n    // would render either nothing or invalid HTML (style tag mid-stream).\n    // After `</head>` (or `</style>` as a fallback for documents that skip\n    // an explicit head close) we know the visual baseline is locked in.\n    useEffect(() => {\n      if (animated && !headClosed) {\n        const lowered = trimmedChildren.toLowerCase();\n        if (lowered.includes('</head>') || lowered.includes('</style>')) {\n          setHeadClosed(true);\n        }\n      }\n    }, [trimmedChildren, animated, headClosed]);\n\n    // Two-phase streaming commit:\n    //   Phase 1 (head still streaming) — don't mount iframe at all. There's\n    //     nothing meaningful to render and styles aren't applied yet.\n    //   Phase 2 (head closed, body streaming) — commit at most once every\n    //     ~250ms. Important: this is a TRUE throttle, not a debounce. The\n    //     pending timer is held in a ref so it survives effect re-runs;\n    //     when it fires it commits the latest content (via another ref)\n    //     and clears itself, allowing a fresh schedule. If chunks come in\n    //     faster than the throttle window (which they do at ~50/sec) we\n    //     still get a commit every 250ms instead of waiting for streaming\n    //     to pause.\n    //   On streaming end → flush immediately, cancel any pending timer.\n    const [throttledContent, setThrottledContent] = useState(trimmedChildren);\n    useEffect(() => {\n      if (!animated) {\n        if (pendingTimerRef.current) {\n          clearTimeout(pendingTimerRef.current);\n          pendingTimerRef.current = null;\n        }\n        lastCommitRef.current = Date.now();\n        setThrottledContent(trimmedChildren);\n        return;\n      }\n      if (!headClosed) return;\n\n      const throttleMs = 250;\n      const now = Date.now();\n      const elapsed = now - lastCommitRef.current;\n\n      if (elapsed >= throttleMs) {\n        if (pendingTimerRef.current) {\n          clearTimeout(pendingTimerRef.current);\n          pendingTimerRef.current = null;\n        }\n        lastCommitRef.current = now;\n        setThrottledContent(trimmedChildren);\n        return;\n      }\n\n      // Schedule a future commit, but only if one isn't already pending —\n      // every chunk arrival re-runs this effect; we don't want to reset\n      // the timer each time (that's debounce, and during continuous\n      // streaming it would never fire).\n      if (pendingTimerRef.current === null) {\n        pendingTimerRef.current = setTimeout(() => {\n          lastCommitRef.current = Date.now();\n          pendingTimerRef.current = null;\n          setThrottledContent(latestContentRef.current);\n        }, throttleMs - elapsed);\n      }\n    }, [trimmedChildren, animated, headClosed]);\n    useEffect(\n      () => () => {\n        if (pendingTimerRef.current) clearTimeout(pendingTimerRef.current);\n      },\n      [],\n    );\n\n    // Live-streaming commitment is sticky for the rest of the session. The\n    // decision is made the moment the head seals:\n    //   • `live` → commit unconditionally\n    //   • `auto` → commit only if no `<script>` has appeared yet (script-\n    //     bearing docs go down the defer path to avoid running setup() on\n    //     partial source)\n    //   • `defer` → never commit; wait for `</html>`\n    // Sticky-ness matters for `auto`: if a `<script>` arrives *after* the\n    // head has already closed and we've started live-streaming, we keep\n    // streaming rather than yanking the rendered content back into a\n    // loading state mid-flight. The shell→static swap at end of streaming\n    // re-runs the document cleanly anyway.\n    useEffect(() => {\n      if (!animated || liveCommitted || !headClosed) return;\n      if (streamingMode === 'live' || (streamingMode === 'auto' && !scriptLocked)) {\n        setLiveCommitted(true);\n      }\n    }, [animated, headClosed, liveCommitted, scriptLocked, streamingMode]);\n\n    // Streaming gate. The iframe can mount in three situations:\n    //   1. content is no longer animating\n    //   2. `</html>` has arrived\n    //   3. live streaming has been committed this session\n    const isStable = !animated || isHtmlContentClosed(trimmedChildren) || liveCommitted;\n\n    const [mode, setMode] = useState<HtmlPreviewMode>(defaultMode);\n\n    // Fragments cannot meaningfully render in preview — force source view.\n    // For streaming content that's not yet stable we keep the user's mode\n    // choice and substitute a loading placeholder in the body instead, so\n    // the toggle UI doesn't flip back and forth as content arrives.\n    const effectiveMode: HtmlPreviewMode = isFragment ? 'source' : mode;\n\n    const contentRef = useRef(trimmedChildren);\n    useEffect(() => {\n      contentRef.current = trimmedChildren;\n    }, [trimmedChildren]);\n\n    // Tail-follow the streaming source visible during Phase 1 — anchor\n    // the scroll position to the latest tokens so a slow model's output\n    // doesn't sit pinned to the document head while the user waits.\n    const loadingSourceRef = useRef<HTMLDivElement | null>(null);\n    useEffect(() => {\n      if (isStable) return;\n      const node = loadingSourceRef.current;\n      if (!node) return;\n      node.scrollTop = node.scrollHeight;\n    }, [trimmedChildren, isStable]);\n\n    const getCopyContent = useCallback(() => contentRef.current, []);\n\n    const handleDownload = useCallback(() => {\n      void downloadHtml(contentRef.current, fileName || 'preview.html');\n    }, [fileName]);\n\n    const handleExpand = useCallback(() => {\n      onExpand?.(contentRef.current);\n    }, [onExpand]);\n\n    const background = themeBackground(theme);\n\n    const sourceBody = useMemo(\n      () => (\n        <SyntaxHighlighter\n          animated={animated}\n          className={classNames?.content}\n          language={'html'}\n          style={{ height: '100%', ...customStyles?.content }}\n          variant={variant}\n        >\n          {trimmedChildren}\n        </SyntaxHighlighter>\n      ),\n      [animated, classNames?.content, customStyles?.content, trimmedChildren, variant],\n    );\n\n    const { styles } = useStyles();\n\n    const iframeBody = useMemo(\n      () => (\n        <HtmlPreviewIframe\n          animated={animated}\n          background={background}\n          className={classNames?.iframe}\n          content={throttledContent}\n          defaultHeight={defaultHeight}\n          sandbox={sandbox}\n          style={customStyles?.iframe}\n        />\n      ),\n      [\n        background,\n        classNames?.iframe,\n        customStyles?.iframe,\n        defaultHeight,\n        sandbox,\n        throttledContent,\n      ],\n    );\n\n    // Shown when the user is on preview mode but the iframe isn't ready\n    // yet (Phase 1 of streaming: head still arriving). Holds the eventual\n    // iframe height to avoid layout shift on mount.\n    //\n    // Stream the raw source through `SyntaxHighlighter` at low opacity so\n    // the user sees real progress on slow models (a 30-tps DeepSeek\n    // pumping a ~5 KB head can otherwise sit on a static spinner for\n    // 20+ seconds). A small \"Preparing preview…\" badge keeps the loading\n    // state unambiguous. Tail-follow keeps the visible region anchored\n    // to the latest tokens — see the `useEffect` below.\n    const loadingBody = useMemo(\n      () => (\n        <div className={styles.loadingRoot} style={{ height: defaultHeight ?? DEFAULT_HEIGHT }}>\n          <div className={styles.loadingSource} ref={loadingSourceRef}>\n            <SyntaxHighlighter animated={animated} language={'html'} variant={'borderless'}>\n              {trimmedChildren}\n            </SyntaxHighlighter>\n          </div>\n          <div className={styles.loadingBackdrop} />\n          <div className={styles.loadingBadge}>\n            <NeuralNetworkLoading size={16} />\n            <span>Preparing preview…</span>\n          </div>\n        </div>\n      ),\n      [animated, defaultHeight, styles, trimmedChildren],\n    );\n\n    const previewBody = isStable ? iframeBody : loadingBody;\n\n    const defaultBody = effectiveMode === 'preview' ? previewBody : sourceBody;\n\n    const body = useMemo(() => {\n      if (!bodyRender) return defaultBody;\n      return bodyRender({\n        content: trimmedChildren,\n        mode: effectiveMode,\n        originalNode: defaultBody,\n      });\n    }, [bodyRender, defaultBody, effectiveMode, trimmedChildren]);\n\n    const segmentOptions = useMemo(\n      () => [\n        { label: 'Preview', value: 'preview' as const },\n        { label: 'Source', value: 'source' as const },\n      ],\n      [],\n    );\n\n    const iconSize = actionIconSize || 'small';\n\n    const originalActions: ReactNode = (\n      <>\n        {!isFragment && (\n          <Segmented\n            options={segmentOptions}\n            size={'small'}\n            value={effectiveMode}\n            onChange={(v) => setMode(v as HtmlPreviewMode)}\n          />\n        )}\n        {copyable && <CopyButton content={getCopyContent} size={iconSize} />}\n        {downloadable && (\n          <ActionIcon\n            icon={Download}\n            size={iconSize}\n            title={'Download HTML'}\n            onClick={handleDownload}\n          />\n        )}\n        {onExpand && (\n          <ActionIcon\n            icon={Expand}\n            size={iconSize}\n            title={'Open full preview'}\n            onClick={handleExpand}\n          />\n        )}\n      </>\n    );\n\n    const actions = actionsRender\n      ? actionsRender({\n          actionIconSize: iconSize,\n          content: trimmedChildren,\n          getContent: getCopyContent,\n          mode: effectiveMode,\n          originalNode: originalActions,\n          setMode,\n        })\n      : originalActions;\n\n    return (\n      <div\n        className={cx(variants({ shadow, variant }), className)}\n        data-code-type=\"html-preview\"\n        data-html-preview-language={language}\n        style={style}\n        {...rest}\n      >\n        <Flexbox\n          horizontal\n          align={'center'}\n          className={cx(styles.toolbar, classNames?.header)}\n          flex={'none'}\n          gap={4}\n          style={customStyles?.header}\n          onClick={stopPropagation}\n        >\n          {actions}\n        </Flexbox>\n        {body}\n      </div>\n    );\n  },\n);\n\nHtmlPreview.displayName = 'HtmlPreview';\n\nexport default HtmlPreview;\n"],"mappings":"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"}