import { jsx, jsxs, Fragment } from "react/jsx-runtime";
import * as React from "react";
import * as DialogPrimitive from "@radix-ui/react-dialog";
import { ChevronLeft, ChevronRight, File, Info, Download, X, FileText, Minus, ChevronDown, Plus } from "lucide-react";
import { cn } from "../../lib/utils.js";
import { Button } from "../Button/button.js";
import { Separator } from "../Separator/separator.js";
import { Input } from "../Input/input.js";
import { Empty } from "../Empty/empty.js";
import { AspectRatio } from "../AspectRatio/aspect-ratio.js";
import { Textarea } from "../Textarea/textarea.js";
import { Field, FieldLabel } from "../Field/field.js";
import { DescriptionList, DescriptionItem } from "../DescriptionList/description-list.js";
import { ItemInlineActionButton } from "../../patterns/element-anatomy/item-anatomy.js";
import { ChromeHeader } from "../../patterns/header-canonical/chrome-header.js";
import { ScrollArea } from "../ScrollArea/scroll-area.js";
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator } from "../DropdownMenu/dropdown-menu.js";
import { useScrollByPage, buildFadeMask, OverflowScrollArrow } from "../../patterns/horizontal-overflow/horizontal-overflow.js";
import { canRenderImage, ImageRenderer } from "./image-renderer.js";
import { useScrollEdges } from "../../hooks/use-overflow-items.js";
const FallbackRenderer = ({ file }) => /* @__PURE__ */ jsx("div", { className: "w-full h-full flex items-center justify-center p-8", children: /* @__PURE__ */ jsx(
  Empty,
  {
    icon: FileText,
    title: file.name,
    description: `無法在瀏覽器中預覽此檔案類型（${file.mimeType || "unknown"}）。請下載後檢視。`
  }
) });
const fallbackRenderer = {
  id: "fallback",
  canRender: () => true,
  component: ({ file }) => /* @__PURE__ */ jsx(FallbackRenderer, { file })
};
const imageRenderer = {
  id: "image",
  canRender: canRenderImage,
  component: ImageRenderer
};
const userRegistered = [];
function registerFileRenderer(renderer) {
  const existingIdx = userRegistered.findIndex((r) => r.id === renderer.id);
  if (existingIdx >= 0) {
    userRegistered[existingIdx] = renderer;
  } else {
    userRegistered.push(renderer);
  }
}
function resolveRenderer(file) {
  for (const r of userRegistered) {
    if (r.canRender(file)) return r;
  }
  if (imageRenderer.canRender(file)) return imageRenderer;
  return fallbackRenderer;
}
const ZOOM_PRESETS = [10, 25, 50, 75, 100, 125, 150, 200, 400];
const ZOOM_FIT_OPTIONS = [
  { value: "fit-width", label: "Fit to width" },
  { value: "fit-page", label: "Fit to page" }
];
function nextZoomIn(current) {
  for (const p of ZOOM_PRESETS) {
    if (p > current) return p;
  }
  return ZOOM_PRESETS[ZOOM_PRESETS.length - 1];
}
function nextZoomOut(current) {
  for (let i = ZOOM_PRESETS.length - 1; i >= 0; i--) {
    if (ZOOM_PRESETS[i] < current) return ZOOM_PRESETS[i];
  }
  return ZOOM_PRESETS[0];
}
const ZoomInput = ({ value, onChange, onFit, labels }) => {
  const [draft, setDraft] = React.useState(`${value}%`);
  const [menuOpen, setMenuOpen] = React.useState(false);
  React.useEffect(() => {
    setDraft(`${value}%`);
  }, [value]);
  const commitDraft = () => {
    const parsed = parseInt(draft.replace(/[^0-9]/g, ""), 10);
    if (Number.isFinite(parsed) && parsed > 0) {
      const clamped = Math.min(400, Math.max(10, parsed));
      onChange(clamped);
      setDraft(`${clamped}%`);
    } else {
      setDraft(`${value}%`);
    }
  };
  return (
    // zoom group = toolbar 按鈕群組,`gap-2`(8px)對齊本 DS 按鈕 gap canonical。
    /* @__PURE__ */ jsxs("div", { className: "inline-flex items-center gap-2", children: [
      /* @__PURE__ */ jsx(
        Button,
        {
          variant: "text",
          size: "sm",
          iconOnly: true,
          startIcon: Minus,
          "aria-label": "縮小",
          disabled: value <= 10,
          onClick: () => onChange(nextZoomOut(value))
        }
      ),
      /* @__PURE__ */ jsxs(DropdownMenu, { open: menuOpen, onOpenChange: setMenuOpen, children: [
        /* @__PURE__ */ jsx(
          Input,
          {
            size: "sm",
            autoWidth: true,
            "aria-label": labels.zoomInput,
            value: draft,
            onChange: (e) => setDraft(e.target.value),
            onBlur: commitDraft,
            onKeyDown: (e) => {
              if (e.key === "Enter") {
                e.preventDefault();
                commitDraft();
                e.target.blur();
              }
            },
            className: "text-center tabular-nums",
            endSlot: /* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
              ItemInlineActionButton,
              {
                icon: ChevronDown,
                "aria-label": labels.zoomMenu,
                size: "sm",
                overlayTrigger: true
              }
            ) })
          }
        ),
        /* @__PURE__ */ jsx(
          DropdownMenuContent,
          {
            align: "end",
            sideOffset: 8,
            className: "min-w-[9rem] w-auto bg-surface-raised text-foreground border-divider",
            "data-theme": "dark",
            children: /* @__PURE__ */ jsxs("div", { "data-theme": "dark", className: "contents", children: [
              ZOOM_FIT_OPTIONS.map((opt) => /* @__PURE__ */ jsx(
                DropdownMenuItem,
                {
                  onSelect: () => onFit(opt.value),
                  children: opt.label
                },
                opt.value
              )),
              /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
              ZOOM_PRESETS.map((p) => {
                const selected = p === value;
                return /* @__PURE__ */ jsxs(
                  DropdownMenuItem,
                  {
                    onSelect: () => onChange(p),
                    "data-state": selected ? "checked" : void 0,
                    className: cn(
                      "tabular-nums",
                      selected && "bg-neutral-selected"
                    ),
                    children: [
                      p,
                      "%"
                    ]
                  },
                  p
                );
              })
            ] })
          }
        )
      ] }),
      /* @__PURE__ */ jsx(
        Button,
        {
          variant: "text",
          size: "sm",
          iconOnly: true,
          startIcon: Plus,
          "aria-label": "放大",
          disabled: value >= 400,
          onClick: () => onChange(nextZoomIn(value))
        }
      )
    ] })
  );
};
ZoomInput.displayName = "ZoomInput";
const Toolbar = ({
  file,
  capabilities,
  zoom,
  onZoomChange,
  onFit,
  infoOpen,
  onInfoToggle,
  onDownload,
  allowDownload,
  onClose,
  labels
}) => {
  return /* @__PURE__ */ jsxs(
    ChromeHeader,
    {
      lockDensity: "lg",
      className: cn(
        // Chrome layer — `bg-surface-raised` 對齊 token semantic「遮蓋型浮層必須不透明」。
        // FileViewer 整體是 overlay,chrome 屬其 raised surface(同 DropdownMenuContent line 244)。
        // 不用 bg-surface(dark = white α8 半透明,outer 透明時失去 backdrop 洗白)。
        // 不用 bg-canvas(那是「頁面最底層」semantic,chrome 不是 page)。
        // ChromeHeader 自帶 flex/items-center/gap-2/shrink-0/h-chrome-header-height/border-b/px-loose
        "bg-surface-raised"
      ),
      children: [
        /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 min-w-0 flex-1", children: [
          /* @__PURE__ */ jsx(File, { size: 16, className: "text-foreground shrink-0", "aria-hidden": true }),
          /* @__PURE__ */ jsx(
            "span",
            {
              className: "text-body-lg text-foreground truncate",
              title: file.name,
              children: file.name
            }
          )
        ] }),
        /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 shrink-0", children: [
          capabilities.zoom && /* @__PURE__ */ jsxs(Fragment, { children: [
            /* @__PURE__ */ jsx(ZoomInput, { value: zoom, onChange: onZoomChange, onFit, labels }),
            /* @__PURE__ */ jsx(Separator, { orientation: "vertical", className: "h-6 mx-1" })
          ] }),
          /* @__PURE__ */ jsx(
            Button,
            {
              variant: "text",
              size: "sm",
              iconOnly: true,
              startIcon: Info,
              "aria-label": infoOpen ? labels.infoToggleCollapse : labels.infoToggleExpand,
              pressed: infoOpen,
              onClick: onInfoToggle
            }
          ),
          allowDownload && /* @__PURE__ */ jsx(
            Button,
            {
              variant: "text",
              size: "sm",
              iconOnly: true,
              startIcon: Download,
              "aria-label": labels.download,
              onClick: onDownload
            }
          ),
          /* @__PURE__ */ jsx(Separator, { orientation: "vertical", className: "h-6 mx-1" }),
          /* @__PURE__ */ jsx(
            Button,
            {
              iconOnly: true,
              dismiss: true,
              size: "sm",
              "data-dismiss": true,
              startIcon: X,
              "aria-label": labels.close,
              onClick: onClose
            }
          )
        ] })
      ]
    }
  );
};
function formatBytes(bytes) {
  if (bytes == null) return void 0;
  if (bytes < 1024) return `${bytes} B`;
  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
  if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
  return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`;
}
const InfoPanel = ({
  file,
  readOnly,
  onDescriptionChange,
  onClose,
  labels
}) => {
  const [draft, setDraft] = React.useState(file.description ?? "");
  React.useEffect(() => {
    setDraft(file.description ?? "");
  }, [file.id, file.description]);
  const commit = () => {
    if (readOnly) return;
    if (draft !== (file.description ?? "")) {
      onDescriptionChange == null ? void 0 : onDescriptionChange(file.id, draft);
    }
  };
  const sizeText = formatBytes(file.size);
  return /* @__PURE__ */ jsxs(
    "aside",
    {
      className: cn(
        // Chrome — bg-surface-raised 同 Toolbar / Filmstrip(token semantic「遮蓋型浮層」)
        "w-80 shrink-0 flex flex-col bg-surface-raised border-l border-divider",
        "h-full"
      ),
      "aria-label": labels.detailPanel,
      children: [
        /* @__PURE__ */ jsxs(ChromeHeader, { lockDensity: "lg", className: "justify-between", children: [
          /* @__PURE__ */ jsx("h3", { className: "text-body-lg font-medium text-foreground", children: labels.detailsHeading }),
          /* @__PURE__ */ jsx(
            Button,
            {
              iconOnly: true,
              dismiss: true,
              size: "sm",
              "data-dismiss": true,
              startIcon: X,
              "aria-label": labels.detailPanelClose,
              onClick: onClose
            }
          )
        ] }),
        /* @__PURE__ */ jsx(ScrollArea, { className: "flex-1 min-h-0", children: /* @__PURE__ */ jsxs("div", { className: cn(
          "flex flex-col gap-[var(--layout-space-loose)]",
          "px-[var(--layout-space-loose)]",
          "pt-[var(--layout-space-tight)] pb-[var(--layout-space-loose)]"
        ), children: [
          /* @__PURE__ */ jsxs(Field, { children: [
            /* @__PURE__ */ jsx(FieldLabel, { children: "說明" }),
            /* @__PURE__ */ jsx(
              Textarea,
              {
                value: draft,
                onChange: (e) => setDraft(e.target.value),
                onBlur: commit,
                readOnly,
                placeholder: readOnly ? labels.descriptionPlaceholderReadOnly : labels.descriptionPlaceholderEdit,
                rows: 5
              }
            )
          ] }),
          /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-[var(--layout-space-tight)]", children: [
            /* @__PURE__ */ jsx("span", { className: "text-body font-normal text-foreground", children: labels.fileInfoHeading }),
            /* @__PURE__ */ jsxs(DescriptionList, { direction: "horizontal", divided: true, children: [
              /* @__PURE__ */ jsx(DescriptionItem, { label: "檔名", children: file.name }),
              /* @__PURE__ */ jsx(DescriptionItem, { label: "類型", children: file.mimeType || "—" }),
              sizeText && /* @__PURE__ */ jsx(DescriptionItem, { label: "大小", children: /* @__PURE__ */ jsx("span", { className: "tabular-nums", children: sizeText }) }),
              file.metadata && Object.entries(file.metadata).map(([k, v]) => /* @__PURE__ */ jsx(DescriptionItem, { label: k, children: String(v) }, k))
            ] })
          ] })
        ] }) })
      ]
    }
  );
};
const THUMB_SIZE = 64;
const Filmstrip = ({ files, activeIndex, onSelect, labels }) => {
  const { scrollRef, atStart, atEnd, canScroll } = useScrollEdges();
  const scrollByPage = useScrollByPage(scrollRef);
  const maskImage = buildFadeMask({ canScroll, atStart, atEnd, reserveArrowWidth: 32 });
  React.useEffect(() => {
    const el = scrollRef.current;
    if (!el) return;
    const active = el.querySelector(`[data-thumb-index="${activeIndex}"]`);
    active == null ? void 0 : active.scrollIntoView({ behavior: "smooth", inline: "center", block: "nearest" });
  }, [activeIndex, scrollRef]);
  return /* @__PURE__ */ jsxs(
    "div",
    {
      className: cn(
        // Chrome — bg-surface-raised 同 Toolbar / InfoPanel(token semantic「遮蓋型浮層」)
        "relative shrink-0 h-24 bg-surface-raised border-t border-divider",
        "flex items-center",
        "px-[var(--layout-space-loose)]"
      ),
      children: [
        canScroll && !atStart && /* @__PURE__ */ jsx(OverflowScrollArrow, { direction: "left", onClick: () => scrollByPage("left") }),
        /* @__PURE__ */ jsx(
          "div",
          {
            ref: scrollRef,
            className: cn(
              "flex items-center",
              // 刻意隱藏 native scrollbar + 用 fade-mask(horizontal-overflow pattern)
              "scrollbar-none overflow-x-auto overflow-y-hidden h-full py-2",
              "w-full"
            ),
            style: {
              maskImage,
              WebkitMaskImage: maskImage
            },
            children: /* @__PURE__ */ jsx(
              "div",
              {
                role: "group",
                "aria-label": labels.filmstripLabel,
                className: "flex items-center gap-[var(--layout-space-tight)] mx-auto shrink-0",
                children: files.map((file, i) => {
                  var _a;
                  const active = i === activeIndex;
                  const isImage = canRenderImage(file);
                  const ext = ((_a = file.name.split(".").pop()) == null ? void 0 : _a.toUpperCase()) ?? "檔";
                  return /* @__PURE__ */ jsx(
                    "button",
                    {
                      type: "button",
                      "aria-current": active ? "true" : void 0,
                      "aria-label": `${i + 1} / ${files.length}:${file.name}`,
                      "data-thumb-index": i,
                      onClick: () => onSelect(i),
                      className: cn(
                        "shrink-0 rounded-md bg-muted overflow-hidden",
                        "outline-none focus-visible:ring-2 focus-visible:ring-ring",
                        "transition-shadow duration-150",
                        active ? "ring-2 ring-primary" : "ring-1 ring-border hover:ring-border-hover"
                      ),
                      style: { width: THUMB_SIZE, height: THUMB_SIZE },
                      children: /* @__PURE__ */ jsx(AspectRatio, { ratio: 1, className: "w-full h-full", children: isImage ? /* @__PURE__ */ jsx(
                        "img",
                        {
                          src: file.url,
                          alt: "",
                          "aria-hidden": true,
                          className: "w-full h-full object-cover",
                          draggable: false
                        }
                      ) : /* @__PURE__ */ jsxs("div", { className: "w-full h-full flex flex-col items-center justify-center gap-0.5", children: [
                        /* @__PURE__ */ jsx(FileText, { size: 20, className: "text-fg-muted", "aria-hidden": true }),
                        /* @__PURE__ */ jsx("span", { className: "text-footnote text-fg-muted font-medium", children: ext })
                      ] }) })
                    },
                    file.id
                  );
                })
              }
            )
          }
        ),
        canScroll && !atEnd && /* @__PURE__ */ jsx(OverflowScrollArrow, { direction: "right", onClick: () => scrollByPage("right") })
      ]
    }
  );
};
const DEFAULT_LABELS = {
  zoomInput: "縮放比例",
  zoomMenu: "開啟縮放選單",
  infoToggleCollapse: "收合詳細資訊面板",
  infoToggleExpand: "展開詳細資訊面板",
  download: "下載檔案",
  close: "關閉檢視器",
  detailPanel: "檔案詳細資訊",
  detailsHeading: "詳細資訊",
  detailPanelClose: "關閉詳細資訊",
  descriptionPlaceholderReadOnly: "尚無說明",
  descriptionPlaceholderEdit: "為這個檔案加上說明…",
  fileInfoHeading: "檔案資訊",
  filmstripLabel: "檔案佇列",
  previousFile: "上一個檔案",
  nextFile: "下一個檔案"
};
const FileViewer = React.forwardRef(function FileViewer2({
  files,
  initialIndex = 0,
  open,
  defaultOpen,
  onOpenChange,
  index: indexProp,
  onIndexChange,
  onDescriptionChange,
  readOnly = false,
  showFilmstrip = false,
  allowDownload = true,
  onDownload,
  labels: labelsOverride,
  ...props
}, ref) {
  const labels = React.useMemo(
    () => ({ ...DEFAULT_LABELS, ...labelsOverride }),
    [labelsOverride]
  );
  const [internalIndex, setInternalIndex] = React.useState(initialIndex);
  const activeIndex = indexProp ?? internalIndex;
  const setIndex = React.useCallback(
    (next) => {
      const clamped = Math.max(0, Math.min(files.length - 1, next));
      if (indexProp === void 0) setInternalIndex(clamped);
      onIndexChange == null ? void 0 : onIndexChange(clamped);
    },
    [files.length, indexProp, onIndexChange]
  );
  React.useEffect(() => {
    if (open && indexProp === void 0) {
      setInternalIndex(Math.max(0, Math.min(files.length - 1, initialIndex)));
    }
  }, [open, initialIndex, files.length, indexProp]);
  const [infoOpen, setInfoOpen] = React.useState(false);
  const [zoom, setZoom] = React.useState(100);
  const [fitRequest, setFitRequest] = React.useState(null);
  const [capabilities, setCapabilities] = React.useState({
    zoom: false
  });
  const file = files[activeIndex];
  const Renderer = file ? resolveRenderer(file) : null;
  const handleFit = React.useCallback((fit) => {
    setFitRequest((prev) => ({ fit, nonce: ((prev == null ? void 0 : prev.nonce) ?? 0) + 1 }));
  }, []);
  const handleDownload = React.useCallback(() => {
    if (!file) return;
    if (onDownload) {
      onDownload(file);
      return;
    }
    const a = document.createElement("a");
    a.href = file.url;
    a.download = file.name;
    a.target = "_blank";
    a.rel = "noopener";
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
  }, [file, onDownload]);
  React.useEffect(() => {
    if (!open) return;
    const handler = (e) => {
      const target = e.target;
      const tag = target == null ? void 0 : target.tagName;
      if (tag === "INPUT" || tag === "TEXTAREA" || (target == null ? void 0 : target.isContentEditable)) return;
      if (e.key === "ArrowLeft" && files.length > 1) {
        e.preventDefault();
        setIndex(activeIndex - 1);
      } else if (e.key === "ArrowRight" && files.length > 1) {
        e.preventDefault();
        setIndex(activeIndex + 1);
      } else if (e.key === "+" || e.key === "=") {
        if (capabilities.zoom) {
          e.preventDefault();
          setZoom((z) => nextZoomIn(z));
        }
      } else if (e.key === "-") {
        if (capabilities.zoom) {
          e.preventDefault();
          setZoom((z) => nextZoomOut(z));
        }
      } else if (e.key === "0") {
        if (capabilities.zoom) {
          e.preventDefault();
          setZoom(100);
        }
      } else if (e.key === "f" || e.key === "F") {
        if (capabilities.zoom) {
          e.preventDefault();
          handleFit("fit-page");
        }
      } else if (e.key === "i" || e.key === "I") {
        e.preventDefault();
        setInfoOpen((o) => !o);
      }
    };
    window.addEventListener("keydown", handler);
    return () => window.removeEventListener("keydown", handler);
  }, [open, activeIndex, files.length, setIndex, capabilities.zoom, handleFit]);
  const [armVisible, setArmVisible] = React.useState(false);
  const idleTimerRef = React.useRef(null);
  const handleViewportMouseMove = React.useCallback(() => {
    setArmVisible(true);
    if (idleTimerRef.current) clearTimeout(idleTimerRef.current);
    idleTimerRef.current = setTimeout(() => setArmVisible(false), 2500);
  }, []);
  const handleViewportMouseLeave = React.useCallback(() => {
    setArmVisible(false);
    if (idleTimerRef.current) clearTimeout(idleTimerRef.current);
  }, []);
  React.useEffect(() => () => {
    if (idleTimerRef.current) clearTimeout(idleTimerRef.current);
  }, []);
  if (!file || !Renderer) {
    return null;
  }
  const showFilmstripResolved = showFilmstrip && files.length > 1;
  const showArrows = files.length > 1;
  return /* @__PURE__ */ jsx(DialogPrimitive.Root, { open, defaultOpen, onOpenChange, children: /* @__PURE__ */ jsxs(DialogPrimitive.Portal, { children: [
    /* @__PURE__ */ jsx(
      DialogPrimitive.Overlay,
      {
        "data-theme": "dark",
        className: cn(
          "fixed inset-0 z-50 bg-overlay",
          "data-[state=open]:animate-in data-[state=closed]:animate-out",
          "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0"
        )
      }
    ),
    /* @__PURE__ */ jsx(
      DialogPrimitive.Content,
      {
        ref,
        className: cn(
          // Edge-to-edge fullscreen,無 inset / 無 radius(與一般 Dialog 差別的所在)
          "fixed inset-0 z-50 outline-none",
          "data-[state=open]:animate-in data-[state=closed]:animate-out",
          "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0"
        ),
        onOpenAutoFocus: (e) => e.preventDefault(),
        ...props,
        children: /* @__PURE__ */ jsxs(
          "div",
          {
            "data-theme": "dark",
            className: "w-full h-full flex flex-col text-foreground",
            children: [
              /* @__PURE__ */ jsxs(DialogPrimitive.Title, { className: "sr-only", children: [
                "檔案檢視器:",
                file.name
              ] }),
              /* @__PURE__ */ jsx(
                Toolbar,
                {
                  file,
                  capabilities,
                  zoom,
                  onZoomChange: setZoom,
                  onFit: handleFit,
                  infoOpen,
                  onInfoToggle: () => setInfoOpen((o) => !o),
                  onDownload: handleDownload,
                  allowDownload,
                  onClose: () => onOpenChange == null ? void 0 : onOpenChange(false),
                  labels
                }
              ),
              /* @__PURE__ */ jsxs("div", { className: "flex-1 min-h-0 flex", children: [
                /* @__PURE__ */ jsxs(
                  "div",
                  {
                    className: "relative flex-1 min-w-0",
                    onMouseMove: handleViewportMouseMove,
                    onMouseLeave: handleViewportMouseLeave,
                    onClick: (e) => {
                      const t = e.target;
                      if (t.closest('button, [role="button"]')) return;
                      const img = e.currentTarget.querySelector("img");
                      if (img) {
                        const r = img.getBoundingClientRect();
                        if (e.clientX >= r.left && e.clientX <= r.right && e.clientY >= r.top && e.clientY <= r.bottom) return;
                      }
                      onOpenChange == null ? void 0 : onOpenChange(false);
                    },
                    children: [
                      showArrows && activeIndex > 0 && /* @__PURE__ */ jsx(
                        "div",
                        {
                          className: cn(
                            "absolute left-[var(--layout-space-loose)] top-1/2 -translate-y-1/2 z-10",
                            "transition-opacity duration-150",
                            // armVisible state 控制,或 focus-within 時 a11y 強制顯示
                            armVisible ? "opacity-100" : "opacity-0 pointer-events-none",
                            "focus-within:opacity-100 focus-within:pointer-events-auto"
                          ),
                          children: /* @__PURE__ */ jsx(
                            Button,
                            {
                              variant: "text",
                              size: "md",
                              iconOnly: true,
                              startIcon: ChevronLeft,
                              "aria-label": labels.previousFile,
                              onClick: () => setIndex(activeIndex - 1)
                            }
                          )
                        }
                      ),
                      /* @__PURE__ */ jsx("div", { className: "w-full h-full", children: /* @__PURE__ */ jsx(
                        Renderer.component,
                        {
                          file,
                          zoom,
                          onZoomChange: setZoom,
                          fitRequest,
                          onCapabilitiesChange: setCapabilities
                        }
                      ) }),
                      showArrows && activeIndex < files.length - 1 && /* @__PURE__ */ jsx(
                        "div",
                        {
                          className: cn(
                            "absolute right-[var(--layout-space-loose)] top-1/2 -translate-y-1/2 z-10",
                            "transition-opacity duration-150",
                            armVisible ? "opacity-100" : "opacity-0 pointer-events-none",
                            "focus-within:opacity-100 focus-within:pointer-events-auto"
                          ),
                          children: /* @__PURE__ */ jsx(
                            Button,
                            {
                              variant: "text",
                              size: "md",
                              iconOnly: true,
                              startIcon: ChevronRight,
                              "aria-label": labels.nextFile,
                              onClick: () => setIndex(activeIndex + 1)
                            }
                          )
                        }
                      )
                    ]
                  }
                ),
                infoOpen && /* @__PURE__ */ jsx(
                  InfoPanel,
                  {
                    file,
                    readOnly,
                    onDescriptionChange,
                    onClose: () => setInfoOpen(false),
                    labels
                  }
                )
              ] }),
              showFilmstripResolved && /* @__PURE__ */ jsx(
                Filmstrip,
                {
                  files,
                  activeIndex,
                  onSelect: setIndex,
                  labels
                }
              )
            ]
          }
        )
      }
    )
  ] }) });
});
FileViewer.displayName = "FileViewer";
const fileViewerMeta = {
  component: "FileViewer",
  family: null,
  // non-family composite / overlay / layout
  variants: {},
  sizes: {},
  states: ["default", "hover", "active", "focus-visible", "disabled"],
  tokens: {
    bg: ["bg-muted", "bg-surface", "bg-surface-raised"],
    fg: ["text-fg-muted", "text-foreground"],
    ring: ["ring-primary", "ring-ring"]
  }
};
export {
  FileViewer,
  fileViewerMeta,
  registerFileRenderer
};
//# sourceMappingURL=file-viewer.js.map
