export { FloatingMenu_default as FloatingMenu, FloatingMenuExample_default as FloatingMenuExample, Navigation_default as Navigation, NavigationItem_default as NavigationItem, NavigationToggle_default as NavigationToggle } from './chunk-2PS5PIXV.mjs';
import { ExperimentCard } from './chunk-OFYBMMWT.mjs';
export { About_default as About, Contact_default as Contact, ExperimentCard, Home_default as Home, ProjectCarousel } from './chunk-OFYBMMWT.mjs';
export { DANMAKU_MAX_LENGTH, DANMAKU_TRACK_COUNT, DEFAULT_MAX_ACTIVE_FIREWORKS, DEFAULT_MAX_PARTICLES, DanmakuPanel, FIREWORK_KIND_LABELS, FireworksCanvas, FireworksControlPanel, MIKU_PALETTE, MikuFireworks3D, NORMAL_PALETTE, WebSocketTransport, useDanmakuController, useFireworksEngine, useFireworksRealtime } from './chunk-CX5GPCCO.mjs';
import { Dialog, DialogContent, Avatar, AvatarImage, AvatarFallback, Button, FilterButtonGroup, BackButton, Grid, Badge } from './chunk-622Y6LTH.mjs';
export { Dialog as AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, DialogDescription as AlertDialogDescription, DialogFooter as AlertDialogFooter, DialogHeader as AlertDialogHeader, DialogOverlay as AlertDialogOverlay, DialogPortal as AlertDialogPortal, DialogTitle as AlertDialogTitle, DialogTrigger as AlertDialogTrigger, Avatar, AvatarFallback, AvatarImage, BackButton, Badge, Button, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, CollisionBalls, ConfirmModal, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, FilterButtonGroup, GenericOrderManager, Grid, Input, Label, Modal, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, Progress, ScrollArea, ScrollBar, SearchBox, SearchResultHint, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, Dialog as Sheet, DialogClose as SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, DialogOverlay as SheetOverlay, DialogPortal as SheetPortal, SheetTitle, DialogTrigger as SheetTrigger, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, Timeline, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, badgeVariants, buttonVariants } from './chunk-622Y6LTH.mjs';
export { ImageMappingPanel, LocalImageMappingPanel } from './chunk-EGJPS7OL.mjs';
import './chunk-LJ4CCSSY.mjs';
import './chunk-Z36R3P62.mjs';
import './chunk-52TN2QSS.mjs';
import './chunk-KZKIH4AS.mjs';
import { useAuth } from './chunk-KW5JH6V6.mjs';
import './chunk-PE5EAHZK.mjs';
import './chunk-AIKEVVDR.mjs';
import { cn } from './chunk-3NHAT7D4.mjs';
export { arrayUtils, cn, debugUtils, errorUtils, fileUtils, formatTime, japaneseUtils, stringUtils, validators } from './chunk-3NHAT7D4.mjs';
export { useAsyncStorage, useElectronStorage, useTaroStorage } from './chunk-NXQVTAOP.mjs';
export { useLocalStorage, useStorage } from './chunk-VVWQTO4Y.mjs';
import './chunk-WEEXCPSE.mjs';
export { ConsoleLoggerAdapter, LogLevel, Logger, createLogger, logger } from './chunk-3DXPQ4YV.mjs';
import './chunk-WMJKH4XE.mjs';
import React3, { useState, useRef, useCallback, useEffect } from 'react';
import { createWorker } from 'tesseract.js';
import { Upload, X, Loader2, FileText, Eraser, Download, MessageSquare, Send, Bot, User, Shield, AlertTriangle, FlaskConical, LogOut, Meh, Frown, Smile } from 'lucide-react';
import { clsx } from 'clsx';
import { useSensors, useSensor, PointerSensor, TouchSensor, KeyboardSensor, DndContext, closestCenter } from '@dnd-kit/core';
import { useSortable, sortableKeyboardCoordinates, SortableContext, rectSortingStrategy, arrayMove } from '@dnd-kit/sortable';
import { CSS } from '@dnd-kit/utilities';

var useOCR = (options = {}) => {
  const [state, setState] = useState({
    isProcessing: false,
    progress: 0,
    status: "idle",
    error: null,
    result: null
  });
  const workerRef = useRef(null);
  const cleanup = useCallback(async () => {
    if (workerRef.current) {
      await workerRef.current.terminate();
      workerRef.current = null;
    }
  }, []);
  const recognize = useCallback(
    async (image) => {
      setState((prev) => ({
        ...prev,
        isProcessing: true,
        error: null,
        progress: 0,
        status: "initializing"
      }));
      try {
        const worker = await createWorker(options.language || "eng", 1, {
          logger: (m) => {
            if (m.status === "recognizing text") {
              setState((prev) => ({
                ...prev,
                status: "recognizing",
                progress: m.progress
              }));
            }
            options.logger?.(m);
          }
        });
        workerRef.current = worker;
        const { data } = await worker.recognize(image);
        const words = data.words || data.blocks?.flatMap((b) => b.paragraphs.flatMap((p) => p.lines.flatMap((l) => l.words))) || [];
        const lines = data.lines || data.blocks?.flatMap((b) => b.paragraphs.flatMap((p) => p.lines)) || [];
        const result = {
          text: data.text,
          confidence: data.confidence,
          words: words.map((w) => ({
            text: w.text,
            confidence: w.confidence,
            bbox: w.bbox
          })),
          lines: lines.map((l) => l.text)
        };
        setState((prev) => ({
          ...prev,
          isProcessing: false,
          progress: 1,
          status: "completed",
          result
        }));
        await worker.terminate();
        workerRef.current = null;
        return result;
      } catch (err) {
        const error = err instanceof Error ? err : new Error(String(err));
        setState((prev) => ({
          ...prev,
          isProcessing: false,
          status: "error",
          error
        }));
        throw error;
      }
    },
    [options]
  );
  useEffect(() => {
    return () => {
      cleanup();
    };
  }, [cleanup]);
  return {
    ...state,
    recognize,
    cleanup
  };
};
var OCRScanner = ({
  onResult,
  className = "",
  language = "eng"
}) => {
  const [imagePreview, setImagePreview] = useState(null);
  const fileInputRef = useRef(null);
  const { recognize, isProcessing, progress, status, result, error } = useOCR({
    language
  });
  const handleFileChange = async (e) => {
    const file = e.target.files?.[0];
    if (!file) return;
    const reader = new FileReader();
    reader.onload = (event) => {
      setImagePreview(event.target?.result);
    };
    reader.readAsDataURL(file);
    try {
      const ocrResult = await recognize(file);
      onResult?.(ocrResult.text);
    } catch (err) {
      console.error("OCR Error:", err);
    }
  };
  const reset = () => {
    setImagePreview(null);
    if (fileInputRef.current) fileInputRef.current.value = "";
  };
  const handleDragOver = (e) => {
    e.preventDefault();
    e.stopPropagation();
  };
  const handleDrop = async (e) => {
    e.preventDefault();
    e.stopPropagation();
    const file = e.dataTransfer.files?.[0];
    if (file && file.type.startsWith("image/")) {
      const mockEvent = { target: { files: [file] } };
      handleFileChange(mockEvent);
    }
  };
  return /* @__PURE__ */ React3.createElement(
    "div",
    {
      className: clsx("p-6 border-2 border-dashed rounded-xl transition-all", isProcessing ? "border-blue-400 bg-blue-50/10" : "border-gray-200 hover:border-blue-400", className),
      onDragOver: handleDragOver,
      onDrop: handleDrop
    },
    !imagePreview ? /* @__PURE__ */ React3.createElement(
      "div",
      {
        className: "flex flex-col items-center justify-center cursor-pointer space-y-4",
        onClick: () => fileInputRef.current?.click()
      },
      /* @__PURE__ */ React3.createElement("div", { className: "p-4 bg-blue-50 rounded-full text-blue-500" }, /* @__PURE__ */ React3.createElement(Upload, { size: 32 })),
      /* @__PURE__ */ React3.createElement("div", { className: "text-center" }, /* @__PURE__ */ React3.createElement("p", { className: "text-lg font-medium text-gray-700" }, "\u70B9\u51FB\u6216\u62D6\u62FD\u56FE\u7247\u8FDB\u884C OCR \u8BC6\u522B"), /* @__PURE__ */ React3.createElement("p", { className: "text-sm text-gray-500" }, "\u652F\u6301 JPG, PNG, WebP"))
    ) : /* @__PURE__ */ React3.createElement("div", { className: "space-y-4" }, /* @__PURE__ */ React3.createElement("div", { className: "relative group rounded-lg overflow-hidden border border-gray-200" }, /* @__PURE__ */ React3.createElement(
      "img",
      {
        src: imagePreview,
        alt: "Preview",
        className: clsx("max-h-64 mx-auto object-contain transition-opacity", isProcessing ? "opacity-50" : "opacity-100")
      }
    ), !isProcessing && /* @__PURE__ */ React3.createElement(
      "button",
      {
        onClick: reset,
        className: "absolute top-2 right-2 p-1 bg-white/80 rounded-full hover:bg-white text-gray-600 shadow-sm"
      },
      /* @__PURE__ */ React3.createElement(X, { size: 18 })
    ), isProcessing && /* @__PURE__ */ React3.createElement("div", { className: "absolute inset-0 flex flex-col items-center justify-center bg-black/5" }, /* @__PURE__ */ React3.createElement(Loader2, { className: "animate-spin text-blue-500 mb-2", size: 32 }), /* @__PURE__ */ React3.createElement("div", { className: "w-48 bg-gray-200 rounded-full h-1.5 overflow-hidden" }, /* @__PURE__ */ React3.createElement(
      "div",
      {
        className: "bg-blue-500 h-full transition-all duration-300",
        style: { width: progress * 100 + "%" }
      }
    )), /* @__PURE__ */ React3.createElement("p", { className: "text-xs font-medium text-blue-600 mt-2" }, status === "initializing" ? "\u6B63\u5728\u52A0\u8F7D\u5F15\u64CE..." : "\u8BC6\u522B\u4E2D " + Math.round(progress * 100) + "%"))), result && !isProcessing && /* @__PURE__ */ React3.createElement("div", { className: "bg-gray-50 p-4 rounded-lg border border-gray-100 animate-in fade-in slide-in-from-bottom-2" }, /* @__PURE__ */ React3.createElement("div", { className: "flex items-center gap-2 mb-2 text-gray-600 font-medium" }, /* @__PURE__ */ React3.createElement(FileText, { size: 18 }), /* @__PURE__ */ React3.createElement("span", null, "\u8BC6\u522B\u7ED3\u679C (\u7F6E\u4FE1\u5EA6: ", Math.round(result.confidence), "%)")), /* @__PURE__ */ React3.createElement("pre", { className: "text-sm text-gray-800 whitespace-pre-wrap font-sans" }, result.text)), error && /* @__PURE__ */ React3.createElement("div", { className: "p-3 bg-red-50 text-red-600 text-sm rounded-lg border border-red-100" }, "\u8BC6\u522B\u5931\u8D25: ", error.message)),
    /* @__PURE__ */ React3.createElement(
      "input",
      {
        type: "file",
        ref: fileInputRef,
        className: "hidden",
        accept: "image/*",
        onChange: handleFileChange,
        disabled: isProcessing
      }
    )
  );
};
var useBackgroundRemoval = (options = {}) => {
  const [state, setState] = useState({
    isProcessing: false,
    progress: 0,
    status: "idle",
    error: null,
    resultBlob: null,
    resultUrl: null
  });
  const remove = useCallback(async (image) => {
    setState((prev) => ({
      ...prev,
      isProcessing: true,
      error: null,
      progress: 0,
      status: "initializing"
    }));
    try {
      const originalKeys = Object.keys;
      const win = typeof window !== "undefined" ? window : globalThis;
      const originalProcess = win.process;
      let backgroundRemoval;
      try {
        Object.keys = function(obj) {
          if (obj === null || obj === void 0) return [];
          return originalKeys.call(Object, obj);
        };
        if (typeof window !== "undefined") {
          try {
            Object.defineProperty(win, "process", {
              value: { env: {}, versions: {}, release: { name: "node" } },
              configurable: true,
              writable: true
            });
          } catch (e) {
          }
        }
        backgroundRemoval = await import('@imgly/background-removal');
      } finally {
        Object.keys = originalKeys;
        if (typeof window !== "undefined" && originalProcess) {
          try {
            Object.defineProperty(win, "process", {
              value: originalProcess,
              configurable: true,
              writable: true
            });
          } catch (e) {
          }
        }
      }
      const { removeBackground } = backgroundRemoval;
      const config = {
        progress: (status, progress) => {
          setState((prev) => ({
            ...prev,
            status,
            progress
          }));
          options.progress?.(status, progress);
        },
        model: options.model || "small",
        publicPath: options.publicPath,
        fetchArgs: options.fetchArgs
      };
      const blob = await removeBackground(image, config);
      const url = URL.createObjectURL(blob);
      setState((prev) => ({
        ...prev,
        isProcessing: false,
        progress: 1,
        status: "completed",
        resultBlob: blob,
        resultUrl: url
      }));
      return { blob, url };
    } catch (err) {
      const msg = err instanceof Error ? err.message : String(err);
      console.error("AI Background Removal Error:", msg);
      setState((prev) => ({
        ...prev,
        isProcessing: false,
        status: "error",
        error: new Error(msg)
      }));
      throw err;
    }
  }, [options]);
  const cleanup = useCallback(() => {
    if (state.resultUrl) {
      URL.revokeObjectURL(state.resultUrl);
    }
  }, [state.resultUrl]);
  useEffect(() => {
    return () => cleanup();
  }, [cleanup]);
  return {
    ...state,
    remove,
    cleanup
  };
};
var BackgroundRemover = ({
  onResult,
  className = ""
}) => {
  const [imagePreview, setImagePreview] = useState(null);
  const fileInputRef = useRef(null);
  const { remove, isProcessing, progress, status, resultUrl, error } = useBackgroundRemoval();
  const handleFileChange = async (e) => {
    const file = e.target.files?.[0];
    if (!file) return;
    const reader = new FileReader();
    reader.onload = (event) => {
      setImagePreview(event.target?.result);
    };
    reader.readAsDataURL(file);
    try {
      const { blob, url } = await remove(file);
      onResult?.(blob, url);
    } catch (err) {
      console.error("Background Removal Error:", err);
    }
  };
  const reset = () => {
    setImagePreview(null);
    if (fileInputRef.current) fileInputRef.current.value = "";
  };
  const downloadResult = () => {
    if (!resultUrl) return;
    const a = document.createElement("a");
    a.href = resultUrl;
    a.download = "removed_background.png";
    a.click();
  };
  return /* @__PURE__ */ React3.createElement("div", { className: clsx("p-6 border-2 border-dashed rounded-xl transition-all", isProcessing ? "border-purple-400 bg-purple-50/10" : "border-gray-200 hover:border-purple-400", className) }, !imagePreview ? /* @__PURE__ */ React3.createElement(
    "div",
    {
      className: "flex flex-col items-center justify-center cursor-pointer space-y-4",
      onClick: () => fileInputRef.current?.click()
    },
    /* @__PURE__ */ React3.createElement("div", { className: "p-4 bg-purple-50 rounded-full text-purple-500" }, /* @__PURE__ */ React3.createElement(Eraser, { size: 32 })),
    /* @__PURE__ */ React3.createElement("div", { className: "text-center" }, /* @__PURE__ */ React3.createElement("p", { className: "text-lg font-medium text-gray-700" }, "\u4E0A\u4F20\u56FE\u7247\u79FB\u9664\u80CC\u666F"), /* @__PURE__ */ React3.createElement("p", { className: "text-sm text-gray-500" }, "\u5EFA\u8BAE\u4F7F\u7528\u4E3B\u4F53\u660E\u786E\u7684\u56FE\u7247"))
  ) : /* @__PURE__ */ React3.createElement("div", { className: "space-y-4" }, /* @__PURE__ */ React3.createElement("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4" }, /* @__PURE__ */ React3.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React3.createElement("p", { className: "text-xs font-medium text-gray-500 uppercase tracking-wider" }, "\u539F\u56FE"), /* @__PURE__ */ React3.createElement("div", { className: "relative rounded-lg overflow-hidden border border-gray-200 bg-gray-50" }, /* @__PURE__ */ React3.createElement("img", { src: imagePreview, alt: "Original", className: "max-h-64 mx-auto object-contain" }))), /* @__PURE__ */ React3.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React3.createElement("p", { className: "text-xs font-medium text-gray-500 uppercase tracking-wider" }, "\u5904\u7406\u7ED3\u679C"), /* @__PURE__ */ React3.createElement("div", { className: "relative rounded-lg overflow-hidden border border-gray-200 bg-grid-slate-100 bg-[size:20px_20px]" }, resultUrl ? /* @__PURE__ */ React3.createElement("img", { src: resultUrl, alt: "Result", className: "max-h-64 mx-auto object-contain animate-in fade-in zoom-in-95 duration-500" }) : /* @__PURE__ */ React3.createElement("div", { className: "h-64 flex flex-col items-center justify-center text-gray-400" }, isProcessing ? /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(Loader2, { className: "animate-spin text-purple-500 mb-2", size: 32 }), /* @__PURE__ */ React3.createElement("div", { className: "w-32 bg-gray-200 rounded-full h-1.5 overflow-hidden" }, /* @__PURE__ */ React3.createElement(
    "div",
    {
      className: "bg-purple-500 h-full transition-all duration-300",
      style: { width: progress * 100 + "%" }
    }
  )), /* @__PURE__ */ React3.createElement("p", { className: "text-[10px] mt-2 font-mono uppercase" }, status.replace(/-/g, " "))) : /* @__PURE__ */ React3.createElement("span", { className: "text-sm italic" }, "\u7B49\u5F85\u5904\u7406..."))))), /* @__PURE__ */ React3.createElement("div", { className: "flex justify-between items-center pt-2" }, !isProcessing && /* @__PURE__ */ React3.createElement(
    "button",
    {
      onClick: reset,
      className: "flex items-center gap-2 px-4 py-2 text-sm font-medium text-gray-600 hover:text-gray-900 transition-colors"
    },
    /* @__PURE__ */ React3.createElement(X, { size: 16 }),
    "\u91CD\u65B0\u5F00\u59CB"
  ), resultUrl && !isProcessing && /* @__PURE__ */ React3.createElement(
    "button",
    {
      onClick: downloadResult,
      className: "flex items-center gap-2 px-6 py-2 bg-purple-600 hover:bg-purple-700 text-white rounded-lg shadow-sm transition-all"
    },
    /* @__PURE__ */ React3.createElement(Download, { size: 16 }),
    "\u4E0B\u8F7D PNG"
  )), error && /* @__PURE__ */ React3.createElement("div", { className: "p-3 bg-red-50 text-red-600 text-sm rounded-lg border border-red-100" }, "\u5904\u7406\u5931\u8D25: ", error.message)), /* @__PURE__ */ React3.createElement(
    "input",
    {
      type: "file",
      ref: fileInputRef,
      className: "hidden",
      accept: "image/*",
      onChange: handleFileChange,
      disabled: isProcessing
    }
  ));
};
var useSentimentAnalysis = (options = {}) => {
  const [state, setState] = useState({
    isProcessing: false,
    status: "idle",
    error: null,
    result: null
  });
  const pipelineRef = useRef(null);
  const analyze = useCallback(async (text) => {
    setState((prev) => ({
      ...prev,
      isProcessing: true,
      error: null,
      status: "loading model"
    }));
    try {
      if (!pipelineRef.current) {
        const originalKeys = Object.keys;
        const win = typeof window !== "undefined" ? window : globalThis;
        const originalProcess = win.process;
        let transformers;
        try {
          Object.keys = function(obj) {
            if (obj === null || obj === void 0) return [];
            return originalKeys.call(Object, obj);
          };
          if (typeof window !== "undefined") {
            try {
              Object.defineProperty(win, "process", {
                value: { env: {}, versions: {}, release: { name: "node" }, nextTick: (cb) => setTimeout(cb, 0) },
                configurable: true,
                writable: true
              });
            } catch (e) {
            }
          }
          transformers = await import('@xenova/transformers');
        } finally {
          Object.keys = originalKeys;
          if (typeof window !== "undefined" && originalProcess) {
            try {
              Object.defineProperty(win, "process", { value: originalProcess, configurable: true, writable: true });
            } catch (e) {
            }
          }
        }
        const { pipeline, env } = transformers;
        env.allowLocalModels = false;
        if (env.backends?.onnx) {
          env.backends.onnx.wasm.proxy = true;
        }
        const defaultModel = "Xenova/distilbert-base-multilingual-cased-sentiments-student";
        pipelineRef.current = await pipeline("sentiment-analysis", options.model || defaultModel);
      }
      setState((prev) => ({ ...prev, status: "analyzing" }));
      const output = await pipelineRef.current(text);
      const resultData = output[0];
      const label = resultData.label.toLowerCase();
      let sentiment = "neutral";
      const negativeKeywords = ["\u7D2F", "\u60E8", "\u7EDD\u671B", "\u96BE\u53D7", "\u4F24\u5FC3", "\u5DEE", "\u574F", "\u7CDF", "\u4E0D\u884C"];
      const hasNegativeKeyword = negativeKeywords.some((k) => text.includes(k));
      if (label.includes("positive") && !hasNegativeKeyword) {
        sentiment = "positive";
      } else if (label.includes("negative") || label.includes("0") || hasNegativeKeyword) {
        sentiment = "negative";
      }
      const result = {
        label: resultData.label,
        score: resultData.score,
        sentiment
      };
      setState((prev) => ({
        ...prev,
        isProcessing: false,
        status: "completed",
        result
      }));
      return result;
    } catch (err) {
      const msg = err instanceof Error ? err.message : String(err);
      console.error("AI Sentiment Error:", msg);
      setState((prev) => ({ ...prev, isProcessing: false, status: "error", error: new Error(msg) }));
      throw err;
    }
  }, [options.model]);
  return { ...state, analyze };
};
var SentimentAnalyzer = ({
  onResult,
  className = "",
  placeholder = "\u8F93\u5165\u4E00\u6BB5\u4E2D\u6587\u6216\u82F1\u6587\uFF0C\u5206\u6790\u5176\u60C5\u611F\u503E\u5411..."
}) => {
  const [text, setText] = useState("");
  const { analyze, isProcessing, status, result, error } = useSentimentAnalysis();
  const handleAnalyze = async () => {
    if (!text.trim() || isProcessing) return;
    try {
      const res = await analyze(text);
      onResult?.(res);
    } catch (err) {
      console.error("Sentiment Analysis Error:", err);
    }
  };
  const getSentimentIcon = () => {
    if (!result) return null;
    switch (result.sentiment) {
      case "positive":
        return /* @__PURE__ */ React3.createElement(Smile, { className: "text-green-500", size: 24 });
      case "negative":
        return /* @__PURE__ */ React3.createElement(Frown, { className: "text-red-500", size: 24 });
      default:
        return /* @__PURE__ */ React3.createElement(Meh, { className: "text-yellow-500", size: 24 });
    }
  };
  const getSentimentColor = () => {
    if (!result) return "";
    switch (result.sentiment) {
      case "positive":
        return "bg-green-50 border-green-200 text-green-700";
      case "negative":
        return "bg-red-50 border-red-200 text-red-700";
      default:
        return "bg-yellow-50 border-yellow-200 text-yellow-700";
    }
  };
  return /* @__PURE__ */ React3.createElement("div", { className: clsx("p-6 border rounded-xl bg-white dark:bg-gray-800 shadow-sm", className) }, /* @__PURE__ */ React3.createElement("div", { className: "flex items-center gap-2 mb-4 text-gray-700 dark:text-gray-300 font-medium" }, /* @__PURE__ */ React3.createElement(MessageSquare, { size: 20 }), /* @__PURE__ */ React3.createElement("span", null, "\u6587\u672C\u60C5\u611F\u5206\u6790")), /* @__PURE__ */ React3.createElement("div", { className: "relative" }, /* @__PURE__ */ React3.createElement(
    "textarea",
    {
      value: text,
      onChange: (e) => setText(e.target.value),
      placeholder,
      className: "w-full h-32 p-4 bg-gray-50 dark:bg-gray-900 border border-gray-200 dark:border-gray-700 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all outline-none resize-none text-gray-800 dark:text-gray-200",
      disabled: isProcessing
    }
  ), /* @__PURE__ */ React3.createElement(
    "button",
    {
      onClick: handleAnalyze,
      disabled: !text.trim() || isProcessing,
      className: "absolute bottom-3 right-3 p-2 bg-blue-600 hover:bg-blue-700 disabled:bg-gray-400 text-white rounded-md transition-colors shadow-sm"
    },
    isProcessing ? /* @__PURE__ */ React3.createElement(Loader2, { className: "animate-spin", size: 18 }) : /* @__PURE__ */ React3.createElement(Send, { size: 18 })
  )), isProcessing && /* @__PURE__ */ React3.createElement("div", { className: "mt-4 flex items-center gap-2 text-sm text-blue-600 animate-pulse" }, /* @__PURE__ */ React3.createElement(Loader2, { size: 14, className: "animate-spin" }), /* @__PURE__ */ React3.createElement("span", null, "\u6B63\u5728\u5206\u6790 (\u9996\u6B21\u8FD0\u884C\u5C06\u52A0\u8F7D\u6A21\u578B\u8D44\u6E90)...")), result && !isProcessing && /* @__PURE__ */ React3.createElement("div", { className: clsx("mt-4 p-4 border rounded-lg flex items-center gap-4 animate-in fade-in slide-in-from-top-2", getSentimentColor()) }, /* @__PURE__ */ React3.createElement("div", { className: "p-2 bg-white rounded-full shadow-sm" }, getSentimentIcon()), /* @__PURE__ */ React3.createElement("div", null, /* @__PURE__ */ React3.createElement("p", { className: "font-bold text-lg capitalize" }, result.sentiment), /* @__PURE__ */ React3.createElement("p", { className: "text-sm opacity-80" }, "\u7F6E\u4FE1\u5EA6: ", (result.score * 100).toFixed(1), "% (", result.label, ")"))), error && /* @__PURE__ */ React3.createElement("div", { className: "mt-4 p-3 bg-red-50 text-red-600 text-sm rounded-lg border border-red-100" }, "\u5206\u6790\u5931\u8D25: ", error.message));
};
var useTextGeneration = (options = {}) => {
  const [state, setState] = useState({
    isProcessing: false,
    status: "idle",
    error: null,
    result: null
  });
  const pipelineRef = useRef(null);
  const generate = useCallback(async (prompt) => {
    console.log("[AI] Generating for prompt:", prompt);
    setState((prev) => ({
      ...prev,
      isProcessing: true,
      error: null,
      status: "initializing"
    }));
    try {
      if (!pipelineRef.current) {
        const originalKeys = Object.keys;
        const win = typeof window !== "undefined" ? window : globalThis;
        const originalProcess = win.process;
        let transformers;
        try {
          Object.keys = function(obj) {
            if (obj === null || obj === void 0) return [];
            return originalKeys.call(Object, obj);
          };
          if (typeof window !== "undefined") {
            try {
              Object.defineProperty(win, "process", {
                value: { env: {}, versions: {}, release: { name: "node" }, nextTick: (cb) => setTimeout(cb, 0), cwd: () => "/", browser: true },
                configurable: true,
                writable: true
              });
            } catch (e) {
            }
          }
          transformers = await import('@xenova/transformers');
        } finally {
          Object.keys = originalKeys;
          if (typeof window !== "undefined" && originalProcess) {
            try {
              Object.defineProperty(win, "process", { value: originalProcess, configurable: true, writable: true });
            } catch (e) {
            }
          }
        }
        const { pipeline, env } = transformers;
        env.allowLocalModels = false;
        if (env.backends?.onnx) {
          env.backends.onnx.wasm.proxy = true;
        }
        const modelName = options.model || "Xenova/LaMini-Flan-T5-77M";
        pipelineRef.current = await pipeline("text2text-generation", modelName, {
          progress_callback: (info) => {
            if (info.status === "progress") {
              setState((prev) => ({ ...prev, status: "loading model: " + Math.round(info.progress) + "%" }));
            }
          }
        });
      }
      setState((prev) => ({ ...prev, status: "thinking" }));
      const output = await pipelineRef.current(prompt, {
        max_new_tokens: options.max_new_tokens || 64,
        temperature: options.temperature || 0.5,
        // 稍微提高温度
        do_sample: true,
        // 开启采样，避免空输出
        top_k: 50,
        repetition_penalty: 1.1
      });
      const result = output[0].generated_text || "";
      console.log("[AI] Raw result:", result);
      setState((prev) => ({
        ...prev,
        isProcessing: false,
        status: "completed",
        result
      }));
      return result;
    } catch (err) {
      const msg = err instanceof Error ? err.message : String(err);
      console.error("[AI] Error:", err);
      setState((prev) => ({ ...prev, isProcessing: false, status: "error", error: new Error(msg) }));
      throw err;
    }
  }, [options.model, options.max_new_tokens, options.temperature]);
  return { ...state, generate };
};
var SmartAssistant = ({ className = "" }) => {
  const [input, setInput] = useState("");
  const [chatHistory, setChatHistory] = useState([]);
  const scrollRef = useRef(null);
  const { generate, isProcessing: isGenerating, status: genStatus } = useTextGeneration();
  useEffect(() => {
    if (scrollRef.current) {
      scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
    }
  }, [chatHistory, isGenerating]);
  const handleSend = async () => {
    if (!input.trim() || isGenerating) return;
    const userMessage = input.trim();
    setInput("");
    setChatHistory((prev) => [...prev, { role: "user", content: userMessage }]);
    let finalContent = "";
    const lowerMessage = userMessage.toLowerCase();
    if (lowerMessage.includes("\u4F60\u597D") || lowerMessage.includes("hello") || lowerMessage.includes("hi")) {
      finalContent = "\u4F60\u597D\u5440\uFF01\u6211\u662F sa2kit \u7684\u672C\u5730 AI \u52A9\u624B\uFF0C\u5F88\u9AD8\u5174\u80FD\u548C\u4F60\u804A\u5929\u3002\u{1F60A}";
    } else if (lowerMessage.includes("\u8C01") || lowerMessage.includes("who are you")) {
      finalContent = "\u6211\u662F\u4E00\u4E2A\u5B8C\u5168\u8FD0\u884C\u5728\u4F60\u6D4F\u89C8\u5668\u672C\u5730\u7684\u5C0F\u578B AI \u6A21\u578B\uFF0C\u6211\u4E0D\u9700\u8981\u670D\u52A1\u5668\uFF0C\u975E\u5E38\u4FDD\u62A4\u4F60\u7684\u9690\u79C1\u3002";
    } else if (lowerMessage.includes("\u5929\u6C14")) {
      finalContent = "\u867D\u7136\u6211\u770B\u4E0D\u89C1\u5916\u9762\u7684\u9633\u5149\uFF0C\u4F46\u542C\u4F60\u7684\u8BED\u6C14\uFF0C\u4ECA\u5929\u4E00\u5B9A\u662F\u4E2A\u9002\u5408\u51FA\u95E8\u7684\u597D\u5929\u6C14\uFF01\u2600\uFE0F";
    } else if (lowerMessage.includes("\u7D2F") || lowerMessage.includes("\u96BE\u8FC7") || lowerMessage.includes("\u7EDD\u671B")) {
      finalContent = "\u542C\u8D77\u6765\u4F60\u73B0\u5728\u5FC3\u60C5\u4E0D\u592A\u597D... \u62B1\u62B1\u4F60\uFF0C\u6211\u4F1A\u4E00\u76F4\u5728\u8FD9\u91CC\u966A\u4F60\u804A\u5929\u7684\u3002\u2764\uFE0F";
    }
    if (finalContent) {
      setTimeout(() => {
        setChatHistory((prev) => [...prev, { role: "assistant", content: finalContent }]);
      }, 500);
      return;
    }
    const prompt = `\u5BF9\u8BDD\u3002
\u4EBA\u8BF4\uFF1A"${userMessage}"
AI\u56DE\u5E94\uFF1A"`;
    try {
      const response = await generate(prompt);
      let modelOutput = response.replace(/^AI回应：|^AI:|^Assistant:|^回答:|^答:|^Answer:/i, "").replace(/[. ]*Positive[. ]*|[. ]*Negative[. ]*|[. ]*Neutral[. ]*/gi, "").replace(/^["'“]|["'”]$/g, "").trim();
      const isEnglishTrash = /[a-zA-Z]{5,}/.test(modelOutput) && !/[一-龥]/.test(modelOutput);
      const isTooShort = modelOutput.length < 1;
      if (isEnglishTrash || isTooShort) {
        console.warn("[AI] Model failure, triggering smart recovery. Raw was:", response);
        modelOutput = "\u55EF\u55EF\uFF0C\u6211\u6B63\u5728\u542C\u3002\u5173\u4E8E\u201C" + userMessage.slice(0, 6) + "...\u201D\uFF0C\u4F60\u8FD8\u6709\u4EC0\u4E48\u60F3\u5206\u4EAB\u7684\u5417\uFF1F";
      }
      setChatHistory((prev) => [...prev, { role: "assistant", content: modelOutput }]);
    } catch (err) {
      setChatHistory((prev) => [...prev, { role: "assistant", content: "\uFF08\u672C\u5730\u6A21\u578B\u601D\u8003\u8FC7\u5EA6\uFF0C\u6682\u65F6\u4F11\u606F\u4E2D...\uFF09" }]);
    }
  };
  return /* @__PURE__ */ React3.createElement("div", { className: clsx("flex flex-col h-[500px] bg-white dark:bg-gray-800 rounded-xl shadow-inner border border-gray-100 dark:border-gray-700 overflow-hidden", className) }, /* @__PURE__ */ React3.createElement("div", { ref: scrollRef, className: "flex-1 overflow-y-auto p-4 space-y-4 bg-gray-50/50 dark:bg-gray-900/50" }, chatHistory.length === 0 && /* @__PURE__ */ React3.createElement("div", { className: "h-full flex flex-col items-center justify-center text-gray-400 space-y-2" }, /* @__PURE__ */ React3.createElement(Bot, { size: 48, className: "opacity-20" }), /* @__PURE__ */ React3.createElement("p", { className: "text-sm italic text-center px-8 text-gray-400 font-sans" }, "\u4F60\u597D\uFF01\u6211\u662F 100% \u672C\u5730\u8FD0\u884C\u7684 AI\u3002", /* @__PURE__ */ React3.createElement("br", null), "\u4F60\u53EF\u4EE5\u548C\u6211\u804A\u804A\u5929\uFF0C\u6211\u4F1A\u5C1D\u8BD5\u7406\u89E3\u4F60\u7684\u610F\u601D\u3002")), chatHistory.map((msg, i) => /* @__PURE__ */ React3.createElement("div", { key: i, className: clsx("flex", msg.role === "user" ? "justify-end" : "justify-start", "animate-in fade-in slide-in-from-bottom-2") }, /* @__PURE__ */ React3.createElement("div", { className: clsx("flex gap-3 max-w-[85%]", msg.role === "user" ? "flex-row-reverse" : "") }, /* @__PURE__ */ React3.createElement("div", { className: clsx("p-2 rounded-lg h-fit", msg.role === "user" ? "bg-blue-100 text-blue-600" : "bg-white dark:bg-gray-700 shadow-sm border border-gray-100 dark:border-gray-600 text-gray-400") }, msg.role === "user" ? /* @__PURE__ */ React3.createElement(User, { size: 18 }) : /* @__PURE__ */ React3.createElement(Bot, { size: 18 })), /* @__PURE__ */ React3.createElement("div", { className: clsx("p-3 rounded-2xl shadow-sm text-sm", msg.role === "user" ? "bg-blue-600 text-white rounded-tr-none" : "bg-white dark:bg-gray-700 text-gray-800 dark:text-gray-200 rounded-tl-none border border-gray-100 dark:border-gray-600 leading-relaxed") }, msg.content)))), isGenerating && /* @__PURE__ */ React3.createElement("div", { className: "flex justify-start" }, /* @__PURE__ */ React3.createElement("div", { className: "flex gap-3 items-center bg-white dark:bg-gray-700 p-3 rounded-2xl rounded-tl-none border border-gray-100 dark:border-gray-600" }, /* @__PURE__ */ React3.createElement(Loader2, { className: "animate-spin text-blue-500", size: 16 }), /* @__PURE__ */ React3.createElement("div", { className: "flex flex-col" }, /* @__PURE__ */ React3.createElement("span", { className: "text-xs text-gray-500 font-medium" }, "\u601D\u8003\u4E2D..."), /* @__PURE__ */ React3.createElement("span", { className: "text-[10px] text-blue-400 font-mono tracking-tighter" }, genStatus))))), /* @__PURE__ */ React3.createElement("div", { className: "p-4 bg-white dark:bg-gray-800 border-t border-gray-100 dark:border-gray-700" }, /* @__PURE__ */ React3.createElement("div", { className: "relative flex items-center gap-2" }, /* @__PURE__ */ React3.createElement(
    "input",
    {
      type: "text",
      value: input,
      onChange: (e) => setInput(e.target.value),
      onKeyDown: (e) => e.key === "Enter" && handleSend(),
      placeholder: "\u8F93\u5165\u6587\u5B57...",
      className: "flex-1 bg-gray-50 dark:bg-gray-900 border-none rounded-full px-5 py-3 pr-12 text-sm focus:ring-2 focus:ring-blue-500 outline-none dark:text-white text-gray-800",
      disabled: isGenerating
    }
  ), /* @__PURE__ */ React3.createElement(
    "button",
    {
      onClick: handleSend,
      disabled: !input.trim() || isGenerating,
      className: "absolute right-1 p-2.5 bg-blue-600 hover:bg-blue-700 disabled:bg-gray-400 text-white rounded-full transition-all shadow-md active:scale-95 flex items-center justify-center"
    },
    /* @__PURE__ */ React3.createElement(Send, { size: 18 })
  ))));
};
var themeStyles = {
  light: "",
  dark: "bg-[#222] text-[#eee] border-[#444]",
  blue: "bg-[#f0f8ff] border-[#1890ff]/20"
};
var ProfileModal = ({
  isOpen,
  onClose,
  data,
  showAvatar = true,
  showContacts = true,
  showSocial = true,
  showBio = true,
  avatarSize = 80,
  onAvatarClick,
  onSocialLinkClick,
  onContactClick,
  themeName = "light",
  className
}) => {
  const renderSocialLinks = () => {
    if (!data.socialLinks || data.socialLinks.length === 0) return null;
    return /* @__PURE__ */ React3.createElement("div", { className: "flex gap-3 mt-2" }, data.socialLinks.map((link, index) => /* @__PURE__ */ React3.createElement(
      "a",
      {
        key: index,
        href: link.url,
        className: cn(
          "w-8 h-8 flex items-center justify-center rounded-full no-underline transition-all hover:-translate-y-0.5",
          themeName === "dark" ? "bg-gray-800 text-gray-200 hover:bg-gray-700" : "bg-gray-100 text-gray-800 hover:bg-gray-200"
        ),
        title: link.type,
        target: "_blank",
        rel: "noopener noreferrer",
        onClick: (e) => {
          if (onSocialLinkClick) {
            e.preventDefault();
            onSocialLinkClick(link.url, link.type);
          }
        }
      },
      link.icon ? /* @__PURE__ */ React3.createElement("span", { className: "text-base" }, link.icon) : /* @__PURE__ */ React3.createElement("span", { className: "text-[10px] font-semibold" }, link.type)
    )));
  };
  const renderContacts = () => {
    if (!data.contacts || Object.keys(data.contacts).length === 0) return null;
    return /* @__PURE__ */ React3.createElement("div", { className: cn(
      "mt-4 border-t pt-4",
      themeName === "dark" ? "border-gray-800" : "border-gray-100"
    ) }, Object.entries(data.contacts).map(([type, value], index) => /* @__PURE__ */ React3.createElement(
      "div",
      {
        key: index,
        className: cn(
          "flex mb-2 cursor-pointer py-1.5 px-2 rounded transition-colors",
          themeName === "dark" ? "hover:bg-gray-800" : "hover:bg-gray-50"
        ),
        onClick: () => onContactClick && onContactClick(type, value)
      },
      /* @__PURE__ */ React3.createElement("span", { className: cn(
        "font-medium w-[70px] shrink-0",
        themeName === "dark" ? "text-gray-400" : "text-gray-500"
      ) }, type, ":"),
      /* @__PURE__ */ React3.createElement("span", { className: themeName === "dark" ? "text-gray-200" : "text-gray-800" }, value)
    )));
  };
  return /* @__PURE__ */ React3.createElement(Dialog, { open: isOpen, onOpenChange: (open) => !open && onClose() }, /* @__PURE__ */ React3.createElement(DialogContent, { className: cn(
    "sm:max-w-[500px] p-0 overflow-hidden border-none shadow-2xl",
    themeStyles[themeName] || "",
    className
  ) }, /* @__PURE__ */ React3.createElement("div", { className: "p-6" }, /* @__PURE__ */ React3.createElement("div", { className: "flex gap-5 mb-5" }, showAvatar && /* @__PURE__ */ React3.createElement(
    "div",
    {
      className: "shrink-0",
      onClick: onAvatarClick,
      style: { cursor: onAvatarClick ? "pointer" : "default" }
    },
    /* @__PURE__ */ React3.createElement(Avatar, { className: "border-2 border-primary/10 shadow-sm", style: { width: avatarSize, height: avatarSize } }, data.avatar && /* @__PURE__ */ React3.createElement(AvatarImage, { src: data.avatar, alt: data.name, className: "object-cover" }), /* @__PURE__ */ React3.createElement(AvatarFallback, { className: "text-xl" }, data.name.substring(0, 2).toUpperCase()))
  ), /* @__PURE__ */ React3.createElement("div", { className: "flex-1 min-w-0 flex flex-col justify-center" }, /* @__PURE__ */ React3.createElement("h2", { className: cn(
    "text-2xl font-bold m-0 mb-1",
    themeName === "dark" ? "text-white" : "text-gray-900"
  ) }, data.name), data.title && /* @__PURE__ */ React3.createElement("div", { className: cn(
    "text-sm mb-2",
    themeName === "dark" ? "text-gray-400" : "text-gray-500"
  ) }, data.title), showSocial && renderSocialLinks())), showBio && data.bio && /* @__PURE__ */ React3.createElement("div", { className: cn(
    "mb-5 leading-relaxed text-sm",
    themeName === "dark" ? "text-gray-300" : "text-gray-600"
  ) }, /* @__PURE__ */ React3.createElement("p", null, data.bio)), showContacts && renderContacts(), data.customContent && /* @__PURE__ */ React3.createElement("div", { className: "mt-5" }, data.customContent))));
};
var ProfileModal_default = ProfileModal;
var BadgeList = ({
  badges,
  className = ""
}) => {
  if (!badges || badges.length === 0) return null;
  return /* @__PURE__ */ React3.createElement("div", { className: cn("flex flex-wrap gap-2 mt-4", className) }, badges.map((badge, index) => /* @__PURE__ */ React3.createElement(
    Badge,
    {
      key: index,
      variant: badge.type === "default" ? "default" : badge.type
    },
    badge.icon && /* @__PURE__ */ React3.createElement("span", { className: "mr-1" }, badge.icon),
    badge.label
  )));
};

// src/profile/internal/Stat.tsx
var Stat = ({
  label,
  value,
  icon,
  className = ""
}) => {
  return /* @__PURE__ */ React.createElement("div", { className: cn("flex flex-col items-center flex-1 text-center", className) }, icon && /* @__PURE__ */ React.createElement("span", { className: "mb-2 text-2xl text-gray-400" }, icon), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("div", { className: "text-lg font-semibold text-gray-800" }, value), /* @__PURE__ */ React.createElement("div", { className: "text-xs text-gray-400 mt-1" }, label)));
};

// src/profile/internal/StatList.tsx
var StatList = ({
  stats,
  className = ""
}) => {
  if (!stats || stats.length === 0) return null;
  return /* @__PURE__ */ React.createElement("div", { className: cn("flex justify-between mt-4 pt-4 border-t border-gray-100", className) }, stats.map((stat, index) => /* @__PURE__ */ React.createElement(Stat, { key: index, ...stat })));
};

// src/profile/ProfileButton.tsx
var exampleProfileData = {
  name: "\u5F20\u4E09",
  avatar: "https://randomuser.me/api/portraits/men/32.jpg",
  title: "\u9AD8\u7EA7\u524D\u7AEF\u5DE5\u7A0B\u5E08",
  bio: "\u4E13\u6CE8\u4E8EReact\u548CNext.js\u5F00\u53D1\u7684\u524D\u7AEF\u5DE5\u7A0B\u5E08\uFF0C\u67095\u5E74\u5DE5\u4F5C\u7ECF\u9A8C\u3002\u70ED\u7231\u5F00\u6E90\uFF0C\u559C\u6B22\u5206\u4EAB\u6280\u672F\u7ECF\u9A8C\u3002",
  contacts: {
    "\u90AE\u7BB1": "zhangsan@example.com",
    "\u7535\u8BDD": "138-8888-8888",
    "\u5730\u5740": "\u4E0A\u6D77\u5E02\u6D66\u4E1C\u65B0\u533A"
  },
  socialLinks: [
    { type: "GitHub", url: "https://github.com/zhangsan", icon: "\u2605" },
    { type: "Twitter", url: "https://twitter.com/zhangsan", icon: "\u2726" },
    { type: "LinkedIn", url: "https://linkedin.com/in/zhangsan", icon: "\u272A" }
  ],
  badges: [
    { label: "React", type: "primary" },
    { label: "Next.js", type: "success" },
    { label: "TypeScript", type: "info" },
    { label: "CSS", type: "default" }
  ],
  stats: [
    { label: "\u9879\u76EE", value: 42 },
    { label: "\u7C89\u4E1D", value: 1024 },
    { label: "\u8BC4\u5206", value: "4.9" }
  ],
  customContent: /* @__PURE__ */ React3.createElement("div", { className: "mt-5 border-t border-gray-100 pt-4" }, /* @__PURE__ */ React3.createElement("h3", { className: "text-sm font-semibold mb-2" }, "\u4E13\u4E1A\u6280\u80FD"), /* @__PURE__ */ React3.createElement("p", { className: "text-sm text-gray-600 leading-relaxed" }, "\u7CBE\u901AReact\u3001Vue\u3001Angular\u7B49\u524D\u7AEF\u6846\u67B6\uFF0C\u719F\u6089TypeScript\u3001JavaScript\u3001CSS3\u3001HTML5\u7B49\u524D\u7AEF\u6280\u672F\u3002 \u6709\u4E30\u5BCC\u7684\u5927\u578B\u9879\u76EE\u5F00\u53D1\u7ECF\u9A8C\uFF0C\u80FD\u72EC\u7ACB\u8D1F\u8D23\u524D\u7AEF\u67B6\u6784\u8BBE\u8BA1\u3002"))
};
var ProfileButton = ({
  data = exampleProfileData,
  buttonText = "\u67E5\u770B\u4E2A\u4EBA\u4FE1\u606F",
  variant = "default",
  size = "default",
  className = "",
  modalTheme = "light"
}) => {
  const [isModalOpen, setIsModalOpen] = useState(false);
  const openModal = () => setIsModalOpen(true);
  const closeModal = () => setIsModalOpen(false);
  const handleContactClick = (type, value) => {
    if (type === "\u90AE\u7BB1") {
      window.open("mailto:" + value);
    } else if (type === "\u7535\u8BDD") {
      window.open("tel:" + value);
    }
  };
  return /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(
    Button,
    {
      variant,
      size,
      onClick: openModal,
      className
    },
    buttonText
  ), /* @__PURE__ */ React3.createElement(
    ProfileModal_default,
    {
      isOpen: isModalOpen,
      onClose: closeModal,
      data,
      themeName: modalTheme,
      onContactClick: handleContactClick,
      onSocialLinkClick: (url) => window.open(url, "_blank")
    },
    data.customContent,
    data.badges && /* @__PURE__ */ React3.createElement(BadgeList, { badges: data.badges }),
    data.stats && /* @__PURE__ */ React3.createElement(StatList, { stats: data.stats })
  ));
};
var AutoOpenModal = ({
  data,
  delay = 500,
  // 默认延迟500毫秒
  themeName = "light",
  onClose
}) => {
  const [isModalOpen, setIsModalOpen] = useState(false);
  useEffect(() => {
    const timer = setTimeout(() => {
      setIsModalOpen(true);
    }, delay);
    return () => clearTimeout(timer);
  }, [delay]);
  const handleClose = () => {
    setIsModalOpen(false);
    if (onClose) {
      onClose();
    }
  };
  const handleContactClick = (type, value) => {
    if (type === "\u90AE\u7BB1") {
      window.open("mailto:" + value);
    } else if (type === "\u7535\u8BDD") {
      window.open("tel:" + value);
    }
  };
  return /* @__PURE__ */ React3.createElement(
    ProfileModal_default,
    {
      isOpen: isModalOpen,
      onClose: handleClose,
      data,
      themeName,
      onContactClick: handleContactClick,
      onSocialLinkClick: (url) => window.open(url, "_blank")
    },
    data.badges && /* @__PURE__ */ React3.createElement(BadgeList, { badges: data.badges }),
    data.stats && /* @__PURE__ */ React3.createElement(StatList, { stats: data.stats })
  );
};
var sizeMap = {
  small: "h-8 w-8",
  medium: "h-12 w-12",
  large: "h-16 w-16"
};
var moodColors = {
  online: "bg-green-500",
  offline: "bg-gray-500",
  away: "bg-yellow-500"
};
var EnhancedAvatar = ({
  src,
  name,
  size = "medium",
  mood = "online",
  statusText,
  onClick,
  className
}) => {
  const sizeClass = typeof size === "string" ? sizeMap[size] : "";
  const customSizeStyle = typeof size === "number" ? { width: size, height: size } : {};
  return /* @__PURE__ */ React3.createElement("div", { className: cn("relative inline-block", className), onClick }, /* @__PURE__ */ React3.createElement(Avatar, { className: cn(sizeClass, onClick && "cursor-pointer hover:ring-2 hover:ring-blue-500 transition-all"), style: customSizeStyle }, src && /* @__PURE__ */ React3.createElement(AvatarImage, { src, alt: name || "Avatar", className: "object-cover" }), /* @__PURE__ */ React3.createElement(AvatarFallback, { className: "bg-primary/10 text-primary-foreground" }, name ? name.substring(0, 2).toUpperCase() : "??")), mood && /* @__PURE__ */ React3.createElement(
    "div",
    {
      className: cn(
        "absolute bottom-0 right-0 rounded-full border-2 border-white",
        moodColors[mood],
        typeof size === "number" ? size > 60 ? "h-4 w-4" : "h-3 w-3" : size === "large" ? "h-4 w-4" : "h-3 w-3"
      )
    }
  ), statusText && /* @__PURE__ */ React3.createElement("div", { className: "absolute -bottom-6 left-1/2 transform -translate-x-1/2 whitespace-nowrap" }, /* @__PURE__ */ React3.createElement("span", { className: "text-xs text-muted-foreground" }, statusText)));
};

// src/testField/utils/index.ts
function filterExperiments(experiments, config) {
  const {
    viewMode = "all",
    searchQuery = "",
    completionFilter = "all"
  } = config;
  return experiments.filter((experiment) => {
    const matchesViewMode = viewMode === "all" || experiment.category === viewMode;
    const query = searchQuery.toLowerCase();
    const matchesSearch = !query || experiment.title.toLowerCase().includes(query) || experiment.description.toLowerCase().includes(query) || experiment.tags.some((tag) => tag.toLowerCase().includes(query));
    const matchesCompletion = (() => {
      switch (completionFilter) {
        case "completed":
          return experiment.isCompleted === true;
        case "incomplete":
          return experiment.isCompleted !== true;
        case "all":
        default:
          return true;
      }
    })();
    return matchesViewMode && matchesSearch && matchesCompletion;
  });
}
function sortExperiments(experiments, sortBy = "title", sortOrder = "asc") {
  return [...experiments].sort((a, b) => {
    let comparison = 0;
    switch (sortBy) {
      case "title":
        comparison = a.title.localeCompare(b.title);
        break;
      case "category":
        comparison = a.category.localeCompare(b.category);
        break;
      case "completion":
        const aCompleted = a.isCompleted ? 1 : 0;
        const bCompleted = b.isCompleted ? 1 : 0;
        comparison = bCompleted - aCompleted;
        break;
      case "createdAt":
        if (!a.createdAt && !b.createdAt) {
          comparison = 0;
        } else if (!a.createdAt) {
          comparison = 1;
        } else if (!b.createdAt) {
          comparison = -1;
        } else {
          comparison = new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime();
        }
        break;
      case "updatedAt":
        if (!a.updatedAt && !b.updatedAt) {
          comparison = 0;
        } else if (!a.updatedAt) {
          comparison = 1;
        } else if (!b.updatedAt) {
          comparison = -1;
        } else {
          comparison = new Date(a.updatedAt).getTime() - new Date(b.updatedAt).getTime();
        }
        break;
      default:
        comparison = 0;
    }
    if (comparison === 0) {
      comparison = a.id.localeCompare(b.id);
    }
    return sortOrder === "asc" ? comparison : -comparison;
  });
}
function getAllTags(experiments) {
  const allTags = experiments.flatMap((experiment) => experiment.tags);
  return Array.from(new Set(allTags)).sort();
}
function getExperimentCounts(experiments) {
  const counts = {
    all: experiments.length,
    utility: 0,
    leisure: 0,
    completed: 0,
    inProgress: 0
  };
  experiments.forEach((experiment) => {
    if (experiment.category === "utility") {
      counts.utility++;
    } else if (experiment.category === "leisure") {
      counts.leisure++;
    }
    if (experiment.isCompleted) {
      counts.completed++;
    } else {
      counts.inProgress++;
    }
  });
  return counts;
}
function validateExperiment(experiment) {
  return !!(experiment.id && experiment.title && experiment.description && experiment.path && experiment.category && Array.isArray(experiment.tags));
}
function getCategoryDisplayName(category) {
  switch (category) {
    case "utility":
      return "\u5B9E\u7528\u5DE5\u5177";
    case "leisure":
      return "\u4F11\u95F2\u5A31\u4E50";
    case "all":
    default:
      return "\u5168\u90E8";
  }
}
function getCategoryColor(category) {
  switch (category) {
    case "utility":
      return "bg-blue-100 text-blue-800 border-blue-200";
    case "leisure":
      return "bg-purple-100 text-purple-800 border-purple-200";
    default:
      return "bg-gray-100 text-gray-800 border-gray-200";
  }
}
function getCompletionFilterDisplayName(filter) {
  switch (filter) {
    case "completed":
      return "\u5DF2\u5B8C\u6210";
    case "incomplete":
      return "\u8FDB\u884C\u4E2D";
    case "all":
    default:
      return "\u5168\u90E8\u72B6\u6001";
  }
}
function getCompletionStatusColor(isCompleted) {
  if (isCompleted) {
    return "bg-green-100 text-green-800 border-green-200";
  }
  return "bg-yellow-100 text-yellow-800 border-yellow-200";
}
function getCompletionStatusText(isCompleted) {
  return isCompleted ? "\u5DF2\u5B8C\u6210" : "\u8FDB\u884C\u4E2D";
}

// src/testField/components/CategoryFilter.tsx
var CategoryFilter = ({
  viewMode,
  onViewModeChange,
  counts,
  className
}) => {
  const options = [
    {
      value: "all",
      label: getCategoryDisplayName("all"),
      icon: "\u{1F4CA}",
      activeColor: {
        bg: "bg-blue-500",
        shadow: "shadow-blue-200"
      },
      showCount: false
    },
    {
      value: "utility",
      label: getCategoryDisplayName("utility"),
      icon: "\u{1F527}",
      activeColor: {
        bg: "bg-green-500",
        shadow: "shadow-green-200"
      },
      count: counts.utility,
      showCount: true
    },
    {
      value: "leisure",
      label: getCategoryDisplayName("leisure"),
      icon: "\u{1F3AE}",
      activeColor: {
        bg: "bg-purple-500",
        shadow: "shadow-purple-200"
      },
      count: counts.leisure,
      showCount: true
    }
  ];
  return /* @__PURE__ */ React3.createElement(
    FilterButtonGroup,
    {
      label: "\u9879\u76EE\u7C7B\u522B",
      value: viewMode,
      options,
      onChange: onViewModeChange,
      className
    }
  );
};
var CompletionFilterComponent = ({
  completionFilter,
  onCompletionFilterChange,
  counts,
  className
}) => {
  const options = [
    {
      value: "all",
      label: getCompletionFilterDisplayName("all"),
      icon: "\u{1F4CA}",
      activeColor: {
        bg: "bg-slate-500",
        shadow: "shadow-slate-200"
      },
      count: counts.all,
      showCount: true
    },
    {
      value: "completed",
      label: getCompletionFilterDisplayName("completed"),
      icon: "\u2705",
      activeColor: {
        bg: "bg-emerald-500",
        shadow: "shadow-emerald-200"
      },
      count: counts.completed,
      showCount: true
    },
    {
      value: "incomplete",
      label: getCompletionFilterDisplayName("incomplete"),
      icon: "\u{1F6A7}",
      activeColor: {
        bg: "bg-orange-500",
        shadow: "shadow-orange-200"
      },
      count: counts.inProgress,
      showCount: true
    }
  ];
  return /* @__PURE__ */ React3.createElement(
    FilterButtonGroup,
    {
      label: "\u5B8C\u6210\u72B6\u6001",
      value: completionFilter,
      options,
      onChange: onCompletionFilterChange,
      className
    }
  );
};
var PageHeader = ({ counts, className }) => {
  return /* @__PURE__ */ React3.createElement("div", { className }, /* @__PURE__ */ React3.createElement("div", { className: "mb-8" }, /* @__PURE__ */ React3.createElement(BackButton, null)), /* @__PURE__ */ React3.createElement("div", { className: "mb-8" }, /* @__PURE__ */ React3.createElement("h1", { className: "text-3xl font-bold text-gray-900" }, "\u5B9E\u9A8C\u7530"), /* @__PURE__ */ React3.createElement("p", { className: "mt-2 text-sm text-gray-600" }, "\u5728\u8FD9\u91CC\uFF0C\u4F60\u53EF\u4EE5\u5C1D\u8BD5\u5404\u79CD\u5B9E\u9A8C\u6027\u7684\u529F\u80FD\u548C\u9879\u76EE"), /* @__PURE__ */ React3.createElement("div", { className: "mt-4 flex flex-wrap gap-4 text-sm text-gray-500" }, /* @__PURE__ */ React3.createElement("span", null, "\u603B\u8BA1: ", counts.all, " \u4E2A\u9879\u76EE"), /* @__PURE__ */ React3.createElement("span", null, "\u5B9E\u7528\u5DE5\u5177: ", counts.utility, " \u4E2A"), /* @__PURE__ */ React3.createElement("span", null, "\u4F11\u95F2\u5A31\u4E50: ", counts.leisure, " \u4E2A"), /* @__PURE__ */ React3.createElement("span", null, "\u5DF2\u5B8C\u6210: ", counts.completed, " \u4E2A"))));
};
function defaultExperimentRenderer(item) {
  return /* @__PURE__ */ React3.createElement(
    ExperimentCard,
    {
      href: item.path,
      title: item.title,
      description: item.description,
      tags: item.tags,
      category: item.category,
      isCompleted: item.isCompleted,
      updatedAt: item.updatedAt,
      createdAt: item.createdAt
    }
  );
}
function ExperimentGrid({
  items,
  renderItem,
  columns = { sm: 1, md: 2, lg: 3, xl: 4 },
  gap = "md",
  className = ""
}) {
  const itemRenderer = renderItem || ((item) => defaultExperimentRenderer(item));
  return /* @__PURE__ */ React3.createElement(
    Grid,
    {
      items,
      renderItem: itemRenderer,
      columns,
      gap,
      className
    }
  );
}
function ExperimentItemGrid({
  experiments,
  ...props
}) {
  return /* @__PURE__ */ React3.createElement(ExperimentGrid, { items: experiments, ...props });
}
var EmptyState = ({ searchQuery, onClearSearch, className }) => {
  return /* @__PURE__ */ React3.createElement("div", { className: clsx("text-center py-12", className) }, /* @__PURE__ */ React3.createElement(
    "svg",
    {
      className: "mx-auto h-12 w-12 text-gray-400",
      fill: "none",
      stroke: "currentColor",
      viewBox: "0 0 24 24"
    },
    /* @__PURE__ */ React3.createElement(
      "path",
      {
        strokeLinecap: "round",
        strokeLinejoin: "round",
        strokeWidth: 2,
        d: "M9.172 16.172a4 4 0 015.656 0M9 12h6m-6-4h6m2 5.291A7.962 7.962 0 0112 15c-2.34 0-4.47.904-6.06 2.384"
      }
    )
  ), /* @__PURE__ */ React3.createElement("h3", { className: "mt-2 text-sm font-medium text-gray-900" }, "\u6CA1\u6709\u627E\u5230\u5339\u914D\u7684\u5B9E\u9A8C\u9879\u76EE"), /* @__PURE__ */ React3.createElement("p", { className: "mt-1 text-sm text-gray-500" }, searchQuery ? "\u5C1D\u8BD5\u8C03\u6574\u641C\u7D22\u5173\u952E\u8BCD\u6216\u7B5B\u9009\u6761\u4EF6" : "\u5F53\u524D\u5206\u7C7B\u4E0B\u6682\u65E0\u5B9E\u9A8C\u9879\u76EE"), searchQuery && /* @__PURE__ */ React3.createElement("div", { className: "mt-4" }, /* @__PURE__ */ React3.createElement(
    "button",
    {
      onClick: onClearSearch,
      className: "inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md text-blue-700 bg-blue-100 hover:bg-blue-200"
    },
    "\u6E05\u9664\u641C\u7D22"
  )));
};
var SortControl = ({
  sortBy,
  sortOrder,
  onSortByChange,
  onSortOrderChange
}) => {
  const sortOptions = [
    { value: "title", label: "\u540D\u79F0" },
    { value: "updatedAt", label: "\u66F4\u65B0\u65F6\u95F4" },
    { value: "createdAt", label: "\u521B\u5EFA\u65F6\u95F4" },
    { value: "category", label: "\u7C7B\u522B" },
    { value: "completion", label: "\u5B8C\u6210\u72B6\u6001" }
  ];
  return /* @__PURE__ */ React3.createElement("div", { className: "flex flex-col sm:flex-row items-start sm:items-center gap-2 sm:gap-4 p-4 bg-white rounded-lg shadow-sm border border-gray-100" }, /* @__PURE__ */ React3.createElement("div", { className: "text-sm font-medium text-gray-700" }, "\u6392\u5E8F\u65B9\u5F0F\uFF1A"), /* @__PURE__ */ React3.createElement("div", { className: "flex flex-wrap gap-2" }, sortOptions.map((option) => /* @__PURE__ */ React3.createElement(
    "button",
    {
      key: option.value,
      className: clsx("px-3 py-1.5 text-sm rounded-full transition-colors", sortBy === option.value ? "bg-blue-100 text-blue-700 font-medium" : "bg-gray-100 text-gray-600 hover:bg-gray-200"),
      onClick: () => onSortByChange(option.value)
    },
    option.label
  ))), /* @__PURE__ */ React3.createElement("div", { className: "ml-auto flex items-center" }, /* @__PURE__ */ React3.createElement(
    "button",
    {
      className: "flex items-center gap-1 px-3 py-1.5 text-sm rounded-full bg-gray-100 hover:bg-gray-200",
      onClick: () => onSortOrderChange(sortOrder === "asc" ? "desc" : "asc")
    },
    sortOrder === "asc" ? /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-4 w-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor" }, /* @__PURE__ */ React3.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M3 4h13M3 8h9m-9 4h6m4 0l4-4m0 0l4 4m-4-4v12" })), /* @__PURE__ */ React3.createElement("span", null, "\u5347\u5E8F")) : /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-4 w-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor" }, /* @__PURE__ */ React3.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M3 4h13M3 8h9m-9 4h9m5-4v12m0 0l-4-4m4 4l4-4" })), /* @__PURE__ */ React3.createElement("span", null, "\u964D\u5E8F"))
  )));
};
var SortModeToggle = ({ sortMode, onSortModeChange }) => {
  return /* @__PURE__ */ React3.createElement("div", { className: "flex flex-col sm:flex-row sm:items-center gap-3 bg-white p-4 rounded-lg shadow-sm border border-gray-100" }, /* @__PURE__ */ React3.createElement("span", { className: "text-sm font-medium text-gray-700" }, "\u6392\u5E8F\u6A21\u5F0F\uFF1A"), /* @__PURE__ */ React3.createElement("div", { className: "flex w-full sm:w-auto p-1 bg-gray-100 rounded-lg" }, /* @__PURE__ */ React3.createElement(
    "button",
    {
      className: clsx("flex-1 sm:flex-initial px-3 py-1.5 text-sm rounded-md transition-colors", sortMode === "auto" ? "bg-white text-blue-700 font-medium shadow-sm" : "text-gray-600 hover:bg-gray-200"),
      onClick: () => onSortModeChange("auto")
    },
    /* @__PURE__ */ React3.createElement("div", { className: "flex items-center justify-center sm:justify-start space-x-1" }, /* @__PURE__ */ React3.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-4 w-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor" }, /* @__PURE__ */ React3.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M3 4h13M3 8h9m-9 4h9m5-4v12m0 0l-4-4m4 4l4-4" })), /* @__PURE__ */ React3.createElement("span", null, "\u81EA\u52A8\u6392\u5E8F"))
  ), /* @__PURE__ */ React3.createElement(
    "button",
    {
      className: clsx("flex-1 sm:flex-initial px-3 py-1.5 text-sm rounded-md transition-colors", sortMode === "manual" ? "bg-white text-blue-700 font-medium shadow-sm" : "text-gray-600 hover:bg-gray-200"),
      onClick: () => onSortModeChange("manual")
    },
    /* @__PURE__ */ React3.createElement("div", { className: "flex items-center justify-center sm:justify-start space-x-1" }, /* @__PURE__ */ React3.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-4 w-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor" }, /* @__PURE__ */ React3.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M7 11.5V14m0-2.5v-6a1.5 1.5 0 113 0m-3 6a1.5 1.5 0 00-3 0v2a7.5 7.5 0 0015 0v-5a1.5 1.5 0 013 0m-6-3V11m0-5.5v-1a1.5 1.5 0 013 0v1m0 0V11m0-5.5a1.5 1.5 0 013 0v3m0 0V11" })), /* @__PURE__ */ React3.createElement("span", null, "\u624B\u52A8\u6392\u5E8F"))
  )));
};
var SortableExperimentItem = ({
  item,
  onMoveUp,
  onMoveDown,
  isFirst,
  isLast
}) => {
  const {
    attributes,
    listeners,
    setNodeRef,
    transform,
    transition,
    isDragging
  } = useSortable({ id: item.id });
  const style = {
    transform: CSS.Transform.toString(transform),
    transition,
    zIndex: isDragging ? 100 : 1,
    opacity: isDragging ? 0.8 : 1,
    position: "relative"
  };
  return /* @__PURE__ */ React3.createElement(
    "div",
    {
      ref: setNodeRef,
      style,
      className: "relative group"
    },
    /* @__PURE__ */ React3.createElement(
      "div",
      {
        ...attributes,
        ...listeners,
        className: "absolute right-2 top-2 w-8 h-8 bg-white/80 hover:bg-white rounded-full flex items-center justify-center shadow-md z-[10]\n                  hidden sm:flex\n                  opacity-0 group-hover:opacity-100 transition-opacity\n                  cursor-grab active:cursor-grabbing\n                  touch-action-none",
        onClick: (e) => e.stopPropagation(),
        "aria-label": "\u62D6\u52A8\u6392\u5E8F"
      },
      /* @__PURE__ */ React3.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-5 w-5 text-gray-500", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor" }, /* @__PURE__ */ React3.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M4 8h16M4 16h16" })),
      /* @__PURE__ */ React3.createElement("span", { className: "absolute top-full mt-1 left-1/2 transform -translate-x-1/2 text-xs bg-gray-800 text-white px-2 py-1 rounded whitespace-nowrap opacity-0 group-hover:opacity-100 transition-opacity" }, "\u62D6\u52A8\u6392\u5E8F")
    ),
    /* @__PURE__ */ React3.createElement("div", { className: "absolute right-2 top-2 flex flex-col gap-2 sm:hidden z-[10]" }, /* @__PURE__ */ React3.createElement(
      "button",
      {
        onClick: (e) => {
          e.stopPropagation();
          onMoveUp?.();
        },
        disabled: isFirst,
        className: clsx("w-8 h-8 rounded-full flex items-center justify-center shadow-md", isFirst ? "bg-gray-200 cursor-not-allowed" : "bg-white/80 hover:bg-white active:bg-gray-100"),
        "aria-label": "\u5411\u4E0A\u79FB\u52A8"
      },
      /* @__PURE__ */ React3.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", className: clsx("h-5 w-5", isFirst ? "text-gray-400" : "text-gray-500"), fill: "none", viewBox: "0 0 24 24", stroke: "currentColor" }, /* @__PURE__ */ React3.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 15l7-7 7 7" }))
    ), /* @__PURE__ */ React3.createElement(
      "button",
      {
        onClick: (e) => {
          e.stopPropagation();
          onMoveDown?.();
        },
        disabled: isLast,
        className: clsx("w-8 h-8 rounded-full flex items-center justify-center shadow-md", isLast ? "bg-gray-200 cursor-not-allowed" : "bg-white/80 hover:bg-white active:bg-gray-100"),
        "aria-label": "\u5411\u4E0B\u79FB\u52A8"
      },
      /* @__PURE__ */ React3.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", className: clsx("h-5 w-5", isLast ? "text-gray-400" : "text-gray-500"), fill: "none", viewBox: "0 0 24 24", stroke: "currentColor" }, /* @__PURE__ */ React3.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 9l-7 7-7-7" }))
    )),
    /* @__PURE__ */ React3.createElement("div", { className: clsx("transition-all", isDragging ? "scale-105 shadow-xl" : "") }, /* @__PURE__ */ React3.createElement(
      ExperimentCard,
      {
        href: item.path,
        title: item.title,
        description: item.description,
        tags: item.tags,
        category: item.category,
        isCompleted: item.isCompleted,
        updatedAt: item.updatedAt,
        createdAt: item.createdAt
      }
    ))
  );
};

// src/testField/components/DraggableExperimentGrid.tsx
var DraggableExperimentGrid = ({
  items: initialItems,
  onOrderChange,
  className = ""
}) => {
  const [items, setItems] = useState(initialItems);
  const [isDragging, setIsDragging] = useState(false);
  const sensors = useSensors(
    useSensor(PointerSensor, {
      activationConstraint: {
        distance: 8
        // 需要拖动8px才激活，避免意外触发
      }
    }),
    useSensor(TouchSensor, {
      activationConstraint: {
        delay: 250,
        // 触摸需要按住250ms才激活，避免与点击冲突
        tolerance: 5
        // 允许的移动容差
      }
    }),
    useSensor(KeyboardSensor, {
      coordinateGetter: sortableKeyboardCoordinates
    })
  );
  function handleDragStart() {
    setIsDragging(true);
  }
  function handleDragEnd(event) {
    setIsDragging(false);
    const { active, over } = event;
    if (over && active.id !== over.id) {
      setItems((currentItems) => {
        const oldIndex = currentItems.findIndex((item) => item.id === active.id);
        const newIndex = currentItems.findIndex((item) => item.id === over.id);
        const newItems = arrayMove(currentItems, oldIndex, newIndex);
        if (onOrderChange) {
          onOrderChange(newItems);
        }
        return newItems;
      });
    }
  }
  const handleMoveUp = (index) => {
    if (index > 0) {
      setItems((currentItems) => {
        const newItems = arrayMove(currentItems, index, index - 1);
        onOrderChange?.(newItems);
        return newItems;
      });
    }
  };
  const handleMoveDown = (index) => {
    if (index < items.length - 1) {
      setItems((currentItems) => {
        const newItems = arrayMove(currentItems, index, index + 1);
        onOrderChange?.(newItems);
        return newItems;
      });
    }
  };
  React3.useEffect(() => {
    setItems(initialItems);
  }, [initialItems]);
  return /* @__PURE__ */ React3.createElement("div", { className: clsx("relative", className) }, /* @__PURE__ */ React3.createElement("div", { className: "mb-4 px-4 py-3 bg-blue-50 text-blue-700 rounded-lg border border-blue-200 text-sm" }, /* @__PURE__ */ React3.createElement("div", { className: "flex items-start sm:items-center" }, /* @__PURE__ */ React3.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-5 w-5 mr-2 flex-shrink-0 mt-0.5 sm:mt-0", viewBox: "0 0 20 20", fill: "currentColor" }, /* @__PURE__ */ React3.createElement("path", { fillRule: "evenodd", d: "M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z", clipRule: "evenodd" })), /* @__PURE__ */ React3.createElement("div", null, /* @__PURE__ */ React3.createElement("p", { className: "mb-1" }, "\u62D6\u62FD\u5361\u7247\u53EF\u4EE5\u81EA\u5B9A\u4E49\u6392\u5E8F\u3002\u70B9\u51FB\u5361\u7247\u53EF\u4EE5\u8BBF\u95EE\u5BF9\u5E94\u7684\u5B9E\u9A8C\u9879\u76EE\u3002"), /* @__PURE__ */ React3.createElement("p", { className: "text-xs text-blue-600 sm:hidden" }, "\u70B9\u51FB\u5361\u7247\u53F3\u4E0A\u89D2\u7684\u4E0A\u4E0B\u7BAD\u5934\u6309\u94AE\u8C03\u6574\u987A\u5E8F"), /* @__PURE__ */ React3.createElement("p", { className: "text-xs text-blue-600 hidden sm:block" }, "\u957F\u6309\u5361\u7247\u53F3\u4E0A\u89D2\u7684\u62D6\u52A8\u56FE\u6807\u8FDB\u884C\u6392\u5E8F")))), /* @__PURE__ */ React3.createElement(
    DndContext,
    {
      sensors,
      collisionDetection: closestCenter,
      onDragStart: handleDragStart,
      onDragEnd: handleDragEnd
    },
    /* @__PURE__ */ React3.createElement(
      SortableContext,
      {
        items: items.map((item) => item.id),
        strategy: rectSortingStrategy
      },
      /* @__PURE__ */ React3.createElement("div", { className: clsx("grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4 md:gap-6", isDragging ? "cursor-grabbing" : "") }, items.map((item, index) => /* @__PURE__ */ React3.createElement(
        SortableExperimentItem,
        {
          key: item.id,
          item,
          onMoveUp: () => handleMoveUp(index),
          onMoveDown: () => handleMoveDown(index),
          isFirst: index === 0,
          isLast: index === items.length - 1
        }
      )))
    )
  ));
};
var PermissionGuard = ({
  apiClient,
  children,
  fallback
}) => {
  const { user, isLoggedIn } = useAuth(apiClient);
  const hasPermission = () => {
    if (!isLoggedIn || !user) {
      return false;
    }
    return true;
  };
  if (!hasPermission()) {
    return fallback || /* @__PURE__ */ React3.createElement("div", { className: "min-h-screen bg-gray-50 flex items-center justify-center" }, /* @__PURE__ */ React3.createElement("div", { className: "max-w-md w-full bg-white rounded-lg shadow-lg p-8 text-center" }, /* @__PURE__ */ React3.createElement("div", { className: "flex items-center justify-center mb-4" }, /* @__PURE__ */ React3.createElement(Shield, { className: "w-12 h-12 text-red-500" })), /* @__PURE__ */ React3.createElement("h2", { className: "text-xl font-semibold text-gray-900 mb-2" }, "\u9700\u8981\u767B\u5F55"), /* @__PURE__ */ React3.createElement("p", { className: "text-gray-600 mb-4" }, "\u8BF7\u5148\u767B\u5F55\u4EE5\u8BBF\u95EE\u5B9E\u9A8C\u7530\u529F\u80FD\u3002"), /* @__PURE__ */ React3.createElement("div", { className: "flex items-center justify-center text-sm text-gray-500 mb-4" }, /* @__PURE__ */ React3.createElement(AlertTriangle, { className: "w-4 h-4 mr-1" }), "\u5B9E\u9A8C\u7530\u5BF9\u6240\u6709\u6CE8\u518C\u7528\u6237\u5F00\u653E"), /* @__PURE__ */ React3.createElement(
      "button",
      {
        onClick: () => window.history.back(),
        className: "inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md text-white bg-green-600 hover:bg-green-700"
      },
      "\u8FD4\u56DE\u4E0A\u4E00\u9875"
    )));
  }
  return /* @__PURE__ */ React3.createElement(React3.Fragment, null, children);
};
var UserInfoBar = ({ apiClient }) => {
  const { user, logout, isLoggedIn } = useAuth(apiClient);
  const handleLogout = async () => {
    try {
      await logout();
      window.location.href = "/";
    } catch (error) {
      console.error("\u767B\u51FA\u5931\u8D25:", error);
    }
  };
  if (!isLoggedIn || !user) {
    return null;
  }
  return /* @__PURE__ */ React3.createElement("div", { className: "bg-white border-b border-gray-200 px-4 py-3" }, /* @__PURE__ */ React3.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ React3.createElement("div", { className: "flex items-center space-x-3" }, /* @__PURE__ */ React3.createElement("div", { className: "flex items-center space-x-2" }, /* @__PURE__ */ React3.createElement(User, { className: "w-5 h-5 text-gray-600" }), /* @__PURE__ */ React3.createElement("span", { className: "text-sm font-medium text-gray-900" }, user.name || user.email || "\u7528\u6237"), user.role && /* @__PURE__ */ React3.createElement("span", { className: "inline-flex items-center px-2 py-1 rounded-full text-xs font-medium bg-green-100 text-green-800" }, user.role))), /* @__PURE__ */ React3.createElement("div", { className: "flex items-center space-x-2" }, /* @__PURE__ */ React3.createElement("div", { className: "flex items-center space-x-1 text-sm text-gray-500" }, /* @__PURE__ */ React3.createElement(FlaskConical, { className: "w-4 h-4" }), /* @__PURE__ */ React3.createElement("span", null, "\u5B9E\u9A8C\u7530")), /* @__PURE__ */ React3.createElement(
    "button",
    {
      onClick: handleLogout,
      className: "inline-flex items-center px-3 py-1.5 border border-gray-300 text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-500"
    },
    /* @__PURE__ */ React3.createElement(LogOut, { className: "w-4 h-4 mr-1" }),
    "\u767B\u51FA"
  ))));
};

export { AutoOpenModal, BackgroundRemover, CategoryFilter, CompletionFilterComponent, DraggableExperimentGrid, EmptyState, EnhancedAvatar, ExperimentGrid, ExperimentItemGrid, OCRScanner, PageHeader, PermissionGuard, ProfileButton, ProfileModal, SentimentAnalyzer, SmartAssistant, SortControl, SortModeToggle, SortableExperimentItem, UserInfoBar, filterExperiments, getAllTags, getCategoryColor, getCategoryDisplayName, getCompletionFilterDisplayName, getCompletionStatusColor, getCompletionStatusText, getExperimentCounts, sortExperiments, useBackgroundRemoval, useOCR, useSentimentAnalysis, useTextGeneration, validateExperiment };
//# sourceMappingURL=index.mjs.map
//# sourceMappingURL=index.mjs.map