{"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":";;;;;;;;;;;;;;;;;AAyBA,MAAM,UAAU,SAAS;;;;AAKzB,MAAM,YAAY,cAAc,EAAE,KAAK,QAAQ,kBAAkB;CAC/D,iBAAiB,GAAG;;;;;;;;;;;QAWd,aAAa,8BAA8B,sBAAsB;;;;;;iBAMxD,QAAQ,QAAQ,OAAO,gBAAgB;;CAEtD,cAAc,GAAG;;;;;;;;;;;;;;;aAeN,OAAO,qBAAqB;;kBAEvB,OAAO,iBAAiB;;4BAEd,OAAO,qBAAqB;;CAMtD,eAAe,GAAG;;;;;;;;;;;;;;;;;;;;;;;;CAwBlB,aAAa,GAAG;;;kBAGA,aAAa,YAAY,UAAU;;CAMnD,SAAS,GACP,iBACA,GAAG;;;;;;;uBAOgB,OAAO,eAAe;;;oBAGzB,OAAO,iBAAiB;;8BAEd,OAAO,qBAAqB;;iCAEzB,OAAO,cAAc;;;;;KAMpD;AACF,EAAE;AAEF,MAAM,mBAAmB,UAA6B;CACpD,IAAI,UAAU,QAAQ,OAAO;CAC7B,IAAI,UAAU,SAAS,OAAO;AAEhC;AAEA,MAAM,eAAe,OAAO,SAAiB,aAAqB;CAChE,MAAM,OAAO,IAAI,KAAK,CAAC,OAAO,GAAG,EAAE,MAAM,0BAA0B,CAAC;CACpE,MAAM,MAAM,IAAI,gBAAgB,IAAI;CACpC,IAAI;EACF,MAAM,aAAa,KAAK,QAAQ;CAClC,UAAU;EACR,IAAI,gBAAgB,GAAG;CACzB;AACF;AAEA,MAAM,cAAc,MACjB,EACC,gBACA,eACA,UACA,YACA,UACA,WACA,YACA,WAAW,MACX,eACA,cAAc,WACd,eAAe,MACf,UACA,WAAW,QACX,UACA,SACA,QACA,gBAAgB,QAChB,OACA,QAAQ,cACR,OACA,UAAU,UAIV,cAAc,eACd,cAAc,eACd,eAAe,gBACf,GAAG,WACC;CACJ,MAAM,kBAAkB,eAAe,YAAY,GAAA,CAAI,KAAK,GAAG,CAAC,QAAQ,CAAC;CACzE,MAAM,aAAa,cAAc,CAAC,mBAAmB,eAAe,GAAG,CAAC,eAAe,CAAC;CAGxF,MAAM,CAAC,cAAc,mBAAmB,SAAS,KAAK;CACtD,MAAM,CAAC,YAAY,iBAAiB,SAAS,KAAK;CAClD,MAAM,CAAC,eAAe,oBAAoB,SAAS,KAAK;CACxD,MAAM,kBAAkB,OAAO,QAAQ;CACvC,MAAM,gBAAgB,OAAO,CAAC;CAC9B,MAAM,kBAAkB,OAA6C,IAAI;CACzE,MAAM,mBAAmB,OAAO,eAAe;CAC/C,gBAAgB;EACd,iBAAiB,UAAU;CAC7B,GAAG,CAAC,eAAe,CAAC;CACpB,gBAAgB;EACd,IAAI,YAAY,CAAC,gBAAgB,SAAS;GACxC,gBAAgB,KAAK;GACrB,cAAc,KAAK;GACnB,iBAAiB,KAAK;GACtB,cAAc,UAAU;GACxB,IAAI,gBAAgB,SAAS;IAC3B,aAAa,gBAAgB,OAAO;IACpC,gBAAgB,UAAU;GAC5B;EACF;EACA,gBAAgB,UAAU;CAC5B,GAAG,CAAC,QAAQ,CAAC;CAIb,gBAAgB;EACd,IAAI,YAAY,CAAC,gBAAgB,eAAe,eAAe,GAC7D,gBAAgB,IAAI;CAExB,GAAG;EAAC;EAAiB;EAAU;CAAY,CAAC;CAM5C,gBAAgB;EACd,IAAI,YAAY,CAAC,YAAY;GAC3B,MAAM,UAAU,gBAAgB,YAAY;GAC5C,IAAI,QAAQ,SAAS,SAAS,KAAK,QAAQ,SAAS,UAAU,GAC5D,cAAc,IAAI;EAEtB;CACF,GAAG;EAAC;EAAiB;EAAU;CAAU,CAAC;CAc1C,MAAM,CAAC,kBAAkB,uBAAuB,SAAS,eAAe;CACxE,gBAAgB;EACd,IAAI,CAAC,UAAU;GACb,IAAI,gBAAgB,SAAS;IAC3B,aAAa,gBAAgB,OAAO;IACpC,gBAAgB,UAAU;GAC5B;GACA,cAAc,UAAU,KAAK,IAAI;GACjC,oBAAoB,eAAe;GACnC;EACF;EACA,IAAI,CAAC,YAAY;EAEjB,MAAM,aAAa;EACnB,MAAM,MAAM,KAAK,IAAI;EACrB,MAAM,UAAU,MAAM,cAAc;EAEpC,IAAI,WAAW,YAAY;GACzB,IAAI,gBAAgB,SAAS;IAC3B,aAAa,gBAAgB,OAAO;IACpC,gBAAgB,UAAU;GAC5B;GACA,cAAc,UAAU;GACxB,oBAAoB,eAAe;GACnC;EACF;EAMA,IAAI,gBAAgB,YAAY,MAC9B,gBAAgB,UAAU,iBAAiB;GACzC,cAAc,UAAU,KAAK,IAAI;GACjC,gBAAgB,UAAU;GAC1B,oBAAoB,iBAAiB,OAAO;EAC9C,GAAG,aAAa,OAAO;CAE3B,GAAG;EAAC;EAAiB;EAAU;CAAU,CAAC;CAC1C,sBACc;EACV,IAAI,gBAAgB,SAAS,aAAa,gBAAgB,OAAO;CACnE,GACA,CAAC,CACH;CAcA,gBAAgB;EACd,IAAI,CAAC,YAAY,iBAAiB,CAAC,YAAY;EAC/C,IAAI,kBAAkB,UAAW,kBAAkB,UAAU,CAAC,cAC5D,iBAAiB,IAAI;CAEzB,GAAG;EAAC;EAAU;EAAY;EAAe;EAAc;CAAa,CAAC;CAMrE,MAAM,WAAW,CAAC,YAAY,oBAAoB,eAAe,KAAK;CAEtE,MAAM,CAAC,MAAM,WAAW,SAA0B,WAAW;CAM7D,MAAM,gBAAiC,aAAa,WAAW;CAE/D,MAAM,aAAa,OAAO,eAAe;CACzC,gBAAgB;EACd,WAAW,UAAU;CACvB,GAAG,CAAC,eAAe,CAAC;CAKpB,MAAM,mBAAmB,OAA8B,IAAI;CAC3D,gBAAgB;EACd,IAAI,UAAU;EACd,MAAM,OAAO,iBAAiB;EAC9B,IAAI,CAAC,MAAM;EACX,KAAK,YAAY,KAAK;CACxB,GAAG,CAAC,iBAAiB,QAAQ,CAAC;CAE9B,MAAM,iBAAiB,kBAAkB,WAAW,SAAS,CAAC,CAAC;CAE/D,MAAM,iBAAiB,kBAAkB;EACvC,aAAkB,WAAW,SAAS,YAAY,cAAc;CAClE,GAAG,CAAC,QAAQ,CAAC;CAEb,MAAM,eAAe,kBAAkB;EACrC,WAAW,WAAW,OAAO;CAC/B,GAAG,CAAC,QAAQ,CAAC;CAEb,MAAM,aAAa,gBAAgB,KAAK;CAExC,MAAM,aAAa,cAEf,oBAAC,mBAAD;EACY;EACV,WAAW,YAAY;EACvB,UAAU;EACV,OAAO;GAAE,QAAQ;GAAQ,GAAG,cAAc;EAAQ;EACzC;YAER;CACgB,CAAA,GAErB;EAAC;EAAU,YAAY;EAAS,cAAc;EAAS;EAAiB;CAAO,CACjF;CAEA,MAAM,EAAE,WAAW,UAAU;CAE7B,MAAM,aAAa,cAEf,oBAAC,mBAAD;EACY;EACE;EACZ,WAAW,YAAY;EACvB,SAAS;EACM;EACN;EACT,OAAO,cAAc;CACtB,CAAA,GAEH;EACE;EACA,YAAY;EACZ,cAAc;EACd;EACA;EACA;CACF,CACF;CAYA,MAAM,cAAc,cAEhB,qBAAC,OAAD;EAAK,WAAW,OAAO;EAAa,OAAO,EAAE,QAAQ,iBAAA,IAAgC;YAArF;GACE,oBAAC,OAAD;IAAK,WAAW,OAAO;IAAe,KAAK;cACzC,oBAAC,mBAAD;KAA6B;KAAU,UAAU;KAAQ,SAAS;eAC/D;IACgB,CAAA;GAChB,CAAA;GACL,oBAAC,OAAD,EAAK,WAAW,OAAO,gBAAkB,CAAA;GACzC,qBAAC,OAAD;IAAK,WAAW,OAAO;cAAvB,CACE,oBAAC,sBAAD,EAAsB,MAAM,GAAK,CAAA,GACjC,oBAAC,QAAD,EAAA,UAAM,qBAAwB,CAAA,CAC3B;;EACF;KAEP;EAAC;EAAU;EAAe;EAAQ;CAAe,CACnD;CAIA,MAAM,cAAc,kBAAkB,YAFlB,WAAW,aAAa,cAEoB;CAEhE,MAAM,OAAO,cAAc;EACzB,IAAI,CAAC,YAAY,OAAO;EACxB,OAAO,WAAW;GAChB,SAAS;GACT,MAAM;GACN,cAAc;EAChB,CAAC;CACH,GAAG;EAAC;EAAY;EAAa;EAAe;CAAe,CAAC;CAE5D,MAAM,iBAAiB,cACf,CACJ;EAAE,OAAO;EAAW,OAAO;CAAmB,GAC9C;EAAE,OAAO;EAAU,OAAO;CAAkB,CAC9C,GACA,CAAC,CACH;CAEA,MAAM,WAAW,kBAAkB;CAEnC,MAAM,kBACJ,qBAAA,YAAA,EAAA,UAAA;EACG,CAAC,cACA,oBAAC,WAAD;GACE,SAAS;GACT,MAAM;GACN,OAAO;GACP,WAAW,MAAM,QAAQ,CAAoB;EAC9C,CAAA;EAEF,YAAY,oBAAC,YAAD;GAAY,SAAS;GAAgB,MAAM;EAAW,CAAA;EAClE,gBACC,oBAAC,YAAD;GACE,MAAM;GACN,MAAM;GACN,OAAO;GACP,SAAS;EACV,CAAA;EAEF,YACC,oBAAC,YAAD;GACE,MAAM;GACN,MAAM;GACN,OAAO;GACP,SAAS;EACV,CAAA;CAEH,EAAA,CAAA;CAGJ,MAAM,UAAU,gBACZ,cAAc;EACZ,gBAAgB;EAChB,SAAS;EACT,YAAY;EACZ,MAAM;EACN,cAAc;EACd;CACF,CAAC,IACD;CAEJ,OACE,qBAAC,OAAD;EACE,WAAW,GAAG,SAAS;GAAE;GAAQ;EAAQ,CAAC,GAAG,SAAS;EACtD,kBAAe;EACf,8BAA4B;EACrB;EACP,GAAI;YALN,CAOE,oBAACA,mBAAD;GACE,YAAA;GACA,OAAO;GACP,WAAW,GAAG,OAAO,SAAS,YAAY,MAAM;GAChD,MAAM;GACN,KAAK;GACL,OAAO,cAAc;GACrB,SAAS;aAER;EACM,CAAA,GACR,IACE;;AAET,CACF;AAEA,YAAY,cAAc"}