mirror of
https://github.com/f/awesome-chatgpt-prompts.git
synced 2026-02-12 07:42:47 +00:00
chore(eslint): update eslint config and downgrade strict rules
This commit is contained in:
@@ -12,7 +12,35 @@ const eslintConfig = defineConfig([
|
||||
"out/**",
|
||||
"build/**",
|
||||
"next-env.d.ts",
|
||||
// Compiled outputs
|
||||
"packages/*/dist/**",
|
||||
// Packages with their own ESLint config
|
||||
"packages/raycast-extension/**",
|
||||
// Scripts - may use CommonJS
|
||||
"scripts/**",
|
||||
// Prisma scripts
|
||||
"prisma/**",
|
||||
]),
|
||||
// Downgrade strict rules to warnings for gradual adoption
|
||||
{
|
||||
rules: {
|
||||
// React hooks compiler rules - many false positives in complex state patterns
|
||||
"react-hooks/set-state-in-effect": "warn",
|
||||
"react-hooks/immutability": "warn",
|
||||
"react-hooks/refs": "warn",
|
||||
"react-hooks/preserve-manual-memoization": "warn",
|
||||
// JSX entity escaping - affects many existing components
|
||||
"react/no-unescaped-entities": "warn",
|
||||
// Function type - affects test mocks
|
||||
"@typescript-eslint/no-unsafe-function-type": "warn",
|
||||
// Display name - affects anonymous components
|
||||
"react/display-name": "warn",
|
||||
// HTML links - sometimes needed for external/special navigation
|
||||
"@next/next/no-html-link-for-pages": "warn",
|
||||
// Children as props - used in some component patterns
|
||||
"react/no-children-prop": "warn",
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
export default eslintConfig;
|
||||
|
||||
@@ -39,6 +39,7 @@ function getJSDocComment(node: ts.Node, sourceFile: ts.SourceFile): { descriptio
|
||||
const examples: string[] = [];
|
||||
let description: string | undefined;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TypeScript AST doesn't expose jsDoc in types
|
||||
const jsDocNodes = (node as any).jsDoc as ts.JSDoc[] | undefined;
|
||||
if (jsDocNodes && jsDocNodes.length > 0) {
|
||||
const jsDoc = jsDocNodes[0];
|
||||
|
||||
@@ -220,7 +220,7 @@ export function PromptList({
|
||||
return (
|
||||
<Box flexDirection="column" height={terminalHeight} padding={1}>
|
||||
<Text color="red">Error: {error}</Text>
|
||||
<Text dimColor>Press 'r' to retry, 'q' to quit</Text>
|
||||
<Text dimColor>Press 'r' to retry, 'q' to quit</Text>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ function parseSimpleYaml(content: string): Record<string, unknown> {
|
||||
const lines = content.split('\n');
|
||||
|
||||
let currentKey: string | null = null;
|
||||
let currentValue: unknown = null;
|
||||
const _currentValue: unknown = null; // Placeholder for future use
|
||||
let inArray = false;
|
||||
let inMultiline = false;
|
||||
let multilineContent = '';
|
||||
|
||||
@@ -16,21 +16,24 @@ interface LevelContentWrapperProps {
|
||||
levelNumber: string;
|
||||
}
|
||||
|
||||
export function LevelContentWrapper({ children, levelSlug, levelNumber }: LevelContentWrapperProps) {
|
||||
export function LevelContentWrapper({ children, levelSlug, levelNumber: _levelNumber }: LevelContentWrapperProps) {
|
||||
const t = useTranslations("kids");
|
||||
const setLevelSlug = useSetLevelSlug();
|
||||
const {
|
||||
currentSection,
|
||||
setCurrentSection,
|
||||
completedSections,
|
||||
const {
|
||||
currentSection,
|
||||
setCurrentSection,
|
||||
completedSections: _completedSections,
|
||||
markSectionComplete,
|
||||
isSectionComplete,
|
||||
isSectionComplete: _isSectionComplete,
|
||||
sectionRequiresCompletion,
|
||||
} = useSectionNavigation();
|
||||
|
||||
|
||||
// Track section completion state from localStorage
|
||||
const [sectionCompletionState, setSectionCompletionState] = useState<Record<number, boolean>>({});
|
||||
|
||||
|
||||
// Track the highest section the user has visited (moved before early returns)
|
||||
const [highestVisitedSection, setHighestVisitedSection] = useState(0);
|
||||
|
||||
// Check localStorage for section completion on mount and when section changes
|
||||
const checkSectionCompletion = useCallback(() => {
|
||||
const newState: Record<number, boolean> = {};
|
||||
@@ -39,27 +42,40 @@ export function LevelContentWrapper({ children, levelSlug, levelNumber }: LevelC
|
||||
}
|
||||
setSectionCompletionState(newState);
|
||||
}, [levelSlug]);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
checkSectionCompletion();
|
||||
// Re-check periodically to catch component completions
|
||||
const interval = setInterval(checkSectionCompletion, 500);
|
||||
return () => clearInterval(interval);
|
||||
}, [checkSectionCompletion, currentSection]);
|
||||
|
||||
|
||||
// Set the level slug in context when component mounts
|
||||
useEffect(() => {
|
||||
setLevelSlug(levelSlug);
|
||||
|
||||
|
||||
// Track level view
|
||||
const level = getLevelBySlug(levelSlug);
|
||||
if (level) {
|
||||
analyticsKids.viewLevel(levelSlug, level.world);
|
||||
}
|
||||
|
||||
|
||||
return () => setLevelSlug(""); // Clear when unmounting
|
||||
}, [levelSlug, setLevelSlug]);
|
||||
|
||||
// Update highest visited when current section changes
|
||||
useEffect(() => {
|
||||
setHighestVisitedSection(prev => Math.max(prev, currentSection));
|
||||
}, [currentSection]);
|
||||
|
||||
// Reset to first section and visited state when level changes
|
||||
useEffect(() => {
|
||||
setCurrentSection(0);
|
||||
setHighestVisitedSection(0);
|
||||
setSectionCompletionState({});
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps -- setCurrentSection is stable
|
||||
}, [levelSlug]);
|
||||
|
||||
// Extract Section components from children
|
||||
const sections: ReactElement[] = [];
|
||||
let hasExplicitSections = false;
|
||||
@@ -104,19 +120,11 @@ export function LevelContentWrapper({ children, levelSlug, levelNumber }: LevelC
|
||||
const totalSections = sections.length;
|
||||
const isFirstSection = currentSection === 0;
|
||||
const isLastSection = currentSection === totalSections - 1;
|
||||
|
||||
|
||||
// Check if current section is complete (from localStorage) OR doesn't require completion
|
||||
const currentSectionRequiresCompletion = sectionRequiresCompletion(currentSection);
|
||||
const isCurrentSectionComplete = !currentSectionRequiresCompletion || sectionCompletionState[currentSection] || false;
|
||||
|
||||
// Track the highest section the user has visited
|
||||
const [highestVisitedSection, setHighestVisitedSection] = useState(0);
|
||||
|
||||
// Update highest visited when current section changes
|
||||
useEffect(() => {
|
||||
setHighestVisitedSection(prev => Math.max(prev, currentSection));
|
||||
}, [currentSection]);
|
||||
|
||||
|
||||
// Can navigate to a section if it's:
|
||||
// 1. The current section
|
||||
// 2. A previously visited section (but NOT future sections)
|
||||
@@ -139,27 +147,20 @@ export function LevelContentWrapper({ children, levelSlug, levelNumber }: LevelC
|
||||
setCurrentSection((prev) => prev - 1);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const handleDotClick = (targetSection: number) => {
|
||||
if (canNavigateToSection(targetSection)) {
|
||||
setCurrentSection(targetSection);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Mark section as complete manually (for sections without interactive elements)
|
||||
const handleMarkComplete = () => {
|
||||
const _handleMarkComplete = () => {
|
||||
markSectionCompleted(levelSlug, currentSection);
|
||||
markSectionComplete(currentSection);
|
||||
checkSectionCompletion();
|
||||
};
|
||||
|
||||
// Reset to first section and visited state when level changes
|
||||
useEffect(() => {
|
||||
setCurrentSection(0);
|
||||
setHighestVisitedSection(0);
|
||||
setSectionCompletionState({});
|
||||
}, [levelSlug]);
|
||||
|
||||
return (
|
||||
<div className="h-full flex flex-col">
|
||||
{/* Content area */}
|
||||
|
||||
@@ -2,9 +2,7 @@
|
||||
|
||||
import { useState, useRef, useEffect } from "react";
|
||||
import Link from "next/link";
|
||||
import Image from "next/image";
|
||||
import { useTranslations, useLocale } from "next-intl";
|
||||
import { formatDistanceToNow } from "@/lib/date";
|
||||
import { getPromptUrl } from "@/lib/urls";
|
||||
import { ArrowBigUp, Lock, Copy, ImageIcon, Download, Play, BadgeCheck, Volume2, Link2 } from "lucide-react";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
@@ -91,7 +89,7 @@ export interface PromptCardProps {
|
||||
export function PromptCard({ prompt, showPinButton = false, isPinned = false }: PromptCardProps) {
|
||||
const t = useTranslations("prompts");
|
||||
const tCommon = useTranslations("common");
|
||||
const locale = useLocale();
|
||||
const _locale = useLocale();
|
||||
const outgoingCount = prompt._count?.outgoingConnections || 0;
|
||||
const incomingCount = prompt._count?.incomingConnections || 0;
|
||||
const isFlowStart = outgoingCount > 0 && incomingCount === 0;
|
||||
@@ -104,7 +102,7 @@ export function PromptCard({ prompt, showPinButton = false, isPinned = false }:
|
||||
const isVideo = prompt.type === "VIDEO";
|
||||
const hasMediaBackground = prompt.type === "IMAGE" || isVideo || (isStructuredInput && !!prompt.mediaUrl && !isAudio);
|
||||
const videoRef = useRef<HTMLVideoElement>(null);
|
||||
const [isVisible, setIsVisible] = useState(false);
|
||||
const [_isVisible, setIsVisible] = useState(false);
|
||||
|
||||
// Autoplay video when visible in viewport
|
||||
useEffect(() => {
|
||||
|
||||
@@ -794,6 +794,7 @@ function FlowGraph({ nodes, edges, currentPromptId, currentUserId, isAdmin, onNo
|
||||
return (
|
||||
<div ref={containerRef} className="relative">
|
||||
<svg ref={svgRef} className="w-full" />
|
||||
{/* eslint-disable-next-line react-hooks/refs -- Container dimensions needed for tooltip positioning */}
|
||||
{hoveredNode && (() => {
|
||||
// Calculate position with viewport awareness
|
||||
const tooltipWidth = 320;
|
||||
|
||||
@@ -6,7 +6,7 @@ import { useTranslations } from "next-intl";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { z } from "zod";
|
||||
import { Loader2, Upload, X, ArrowDown, Play, Image as ImageIcon, Video, Volume2, Paperclip, Search, Sparkles, BookOpen, ExternalLink, ChevronDown, Settings2 } from "lucide-react";
|
||||
import { Loader2, Upload, X, ArrowDown, Image as ImageIcon, Video, Volume2, Paperclip, Search, Sparkles, BookOpen, ExternalLink, ChevronDown, Settings2 } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
import { VariableToolbar } from "./variable-toolbar";
|
||||
import { VariableWarning } from "./variable-warning";
|
||||
@@ -21,17 +21,10 @@ import { Input } from "@/components/ui/input";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import {
|
||||
parseSkillFiles,
|
||||
serializeSkillFiles,
|
||||
getLanguageFromFilename,
|
||||
validateFilename,
|
||||
suggestFilename,
|
||||
generateSkillContentWithFrontmatter,
|
||||
updateSkillFrontmatter,
|
||||
validateSkillFrontmatter,
|
||||
DEFAULT_SKILL_FILE,
|
||||
DEFAULT_SKILL_CONTENT,
|
||||
type SkillFile,
|
||||
} from "@/lib/skill-files";
|
||||
import {
|
||||
Form,
|
||||
@@ -61,7 +54,7 @@ import { toast } from "sonner";
|
||||
import { prettifyJson } from "@/lib/format";
|
||||
import { analyticsPrompt } from "@/lib/analytics";
|
||||
import { getPromptUrl } from "@/lib/urls";
|
||||
import { AI_MODELS, getModelsByProvider, type PromptMCPConfig } from "@/lib/works-best-with";
|
||||
import { AI_MODELS, getModelsByProvider } from "@/lib/works-best-with";
|
||||
|
||||
interface MediaFieldProps {
|
||||
form: ReturnType<typeof useForm<PromptFormValues>>;
|
||||
@@ -1324,6 +1317,7 @@ export function PromptForm({ categories, tags, initialData, initialContributors
|
||||
</div>
|
||||
{/* Code output content */}
|
||||
<div className="p-4 text-xs space-y-1" style={{ fontFamily: 'ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace' }}>
|
||||
{/* eslint-disable-next-line react/jsx-no-comment-textnodes -- Intentional code preview text */}
|
||||
<div><span className="text-[#6a9955]">// Code generated by skill...</span></div>
|
||||
<div><span className="text-[#c586c0]">export</span> <span className="text-[#569cd6]">function</span> <span className="text-[#dcdcaa]">handler</span><span className="text-[#d4d4d4]">()</span> <span className="text-[#d4d4d4]">{'{'}</span></div>
|
||||
<div><span className="text-[#d4d4d4]"> </span><span className="text-[#c586c0]">return</span> <span className="text-[#ce9178]">"..."</span><span className="text-[#d4d4d4]">;</span></div>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import Link from "next/link";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { Sparkles, ArrowBigUp } from "lucide-react";
|
||||
import { ArrowBigUp } from "lucide-react";
|
||||
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { getPromptUrl } from "@/lib/urls";
|
||||
|
||||
@@ -316,6 +316,7 @@ export function RunPromptButton({
|
||||
if (url.startsWith("http://") || url.startsWith("https://")) {
|
||||
window.open(url, "_blank");
|
||||
} else {
|
||||
// eslint-disable-next-line react-hooks/immutability -- Valid browser navigation for custom URL schemes
|
||||
window.location.href = url;
|
||||
}
|
||||
analyticsPrompt.run(promptId, platform.name);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useState, useCallback, useMemo, useEffect } from "react";
|
||||
import { useState, useCallback, useMemo } from "react";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { useTheme } from "next-themes";
|
||||
import { DiffEditor } from "@monaco-editor/react";
|
||||
|
||||
@@ -32,7 +32,6 @@ import {
|
||||
validateFilename,
|
||||
suggestFilename,
|
||||
DEFAULT_SKILL_FILE,
|
||||
DEFAULT_SKILL_CONTENT,
|
||||
type SkillFile,
|
||||
} from "@/lib/skill-files";
|
||||
|
||||
@@ -357,6 +356,7 @@ export function SkillEditor({ value, onChange, className }: SkillEditorProps) {
|
||||
|
||||
// Only update if the value changed externally
|
||||
if (value !== currentSerialized) {
|
||||
// eslint-disable-next-line react-hooks/set-state-in-effect -- Intentional sync from external prop
|
||||
setFiles(parsed);
|
||||
// Ensure active file exists
|
||||
if (!parsed.some((f) => f.filename === activeFile)) {
|
||||
@@ -372,7 +372,7 @@ export function SkillEditor({ value, onChange, className }: SkillEditorProps) {
|
||||
|
||||
// File icon based on extension
|
||||
const getFileIcon = (filename: string) => {
|
||||
const ext = filename.split(".").pop()?.toLowerCase();
|
||||
const _ext = filename.split(".").pop()?.toLowerCase();
|
||||
// Could add more specific icons here
|
||||
return <File className="h-4 w-4 text-muted-foreground" />;
|
||||
};
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import { useMemo } from "react";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { AlertTriangle, Braces, FileCode } from "lucide-react";
|
||||
import { Braces, FileCode } from "lucide-react";
|
||||
import { Alert, AlertDescription } from "@/components/ui/alert";
|
||||
import { Button } from "@/components/ui/button";
|
||||
|
||||
|
||||
@@ -101,12 +101,12 @@ export function CodeView({ content, language = "json", className, maxLines, font
|
||||
</div>
|
||||
)}
|
||||
{viewMode === "tree" && isValidJson ? (
|
||||
<JsonTreeViewWrapper
|
||||
content={content}
|
||||
className={className}
|
||||
<JsonTreeViewWrapper
|
||||
content={content}
|
||||
className={className}
|
||||
fontSize={fontSize}
|
||||
onExpandAll={expandAllRef}
|
||||
onCollapseAll={collapseAllRef}
|
||||
onExpandAllRef={expandAllRef}
|
||||
onCollapseAllRef={collapseAllRef}
|
||||
/>
|
||||
) : (
|
||||
<pre suppressHydrationWarning className={cn("font-mono bg-muted rounded p-2", preview ? "overflow-hidden" : "overflow-y-auto max-h-[500px]", {
|
||||
|
||||
@@ -2,10 +2,8 @@
|
||||
|
||||
import { useState, useMemo, useCallback, useEffect } from "react";
|
||||
import type React from "react";
|
||||
import { ChevronRight, ChevronDown, ChevronsDown, ChevronsUp } from "lucide-react";
|
||||
import { ChevronRight, ChevronDown } from "lucide-react";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
interface JsonNode {
|
||||
key: string | null;
|
||||
@@ -14,17 +12,46 @@ interface JsonNode {
|
||||
path: string;
|
||||
}
|
||||
|
||||
// Pure helper function - defined outside component to avoid recreation
|
||||
const getNodeType = (value: unknown): JsonNode["type"] => {
|
||||
if (value === null) return "null";
|
||||
if (Array.isArray(value)) return "array";
|
||||
if (typeof value === "object") return "object";
|
||||
return typeof value as "string" | "number" | "boolean";
|
||||
};
|
||||
|
||||
// Recursive helper function - defined outside component
|
||||
const collectExpandablePaths = (value: unknown, path: string, maxDepth: number, depth: number = 0): string[] => {
|
||||
const paths: string[] = [];
|
||||
const type = getNodeType(value);
|
||||
|
||||
if ((type === "object" || type === "array") && depth < maxDepth) {
|
||||
paths.push(path);
|
||||
|
||||
if (type === "array") {
|
||||
(value as unknown[]).forEach((item, index) => {
|
||||
paths.push(...collectExpandablePaths(item, `${path}.${index}`, maxDepth, depth + 1));
|
||||
});
|
||||
} else {
|
||||
Object.entries(value as Record<string, unknown>).forEach(([k, v]) => {
|
||||
paths.push(...collectExpandablePaths(v, `${path}.${k}`, maxDepth, depth + 1));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return paths;
|
||||
};
|
||||
|
||||
interface JsonTreeViewProps {
|
||||
data: unknown;
|
||||
className?: string;
|
||||
fontSize?: "xs" | "sm" | "base";
|
||||
maxDepth?: number;
|
||||
onExpandAll?: React.MutableRefObject<(() => void) | undefined>;
|
||||
onCollapseAll?: React.MutableRefObject<(() => void) | undefined>;
|
||||
onExpandAllRef?: React.MutableRefObject<(() => void) | undefined>;
|
||||
onCollapseAllRef?: React.MutableRefObject<(() => void) | undefined>;
|
||||
}
|
||||
|
||||
function JsonTreeView({ data, className, fontSize = "xs", maxDepth = 10, onExpandAll, onCollapseAll }: JsonTreeViewProps) {
|
||||
const t = useTranslations("common");
|
||||
function JsonTreeView({ data, className, fontSize = "xs", maxDepth = 10, onExpandAllRef, onCollapseAllRef }: JsonTreeViewProps) {
|
||||
const [expandedPaths, setExpandedPaths] = useState<Set<string>>(new Set(["root"]));
|
||||
|
||||
const togglePath = (path: string) => {
|
||||
@@ -39,38 +66,9 @@ function JsonTreeView({ data, className, fontSize = "xs", maxDepth = 10, onExpan
|
||||
});
|
||||
};
|
||||
|
||||
const getNodeType = (value: unknown): JsonNode["type"] => {
|
||||
if (value === null) return "null";
|
||||
if (Array.isArray(value)) return "array";
|
||||
if (typeof value === "object") return "object";
|
||||
return typeof value as "string" | "number" | "boolean";
|
||||
};
|
||||
|
||||
// Collect all expandable paths recursively
|
||||
const collectExpandablePaths = useCallback((value: unknown, path: string, depth: number = 0): string[] => {
|
||||
const paths: string[] = [];
|
||||
const type = getNodeType(value);
|
||||
|
||||
if ((type === "object" || type === "array") && depth < maxDepth) {
|
||||
paths.push(path);
|
||||
|
||||
if (type === "array") {
|
||||
(value as unknown[]).forEach((item, index) => {
|
||||
paths.push(...collectExpandablePaths(item, `${path}.${index}`, depth + 1));
|
||||
});
|
||||
} else {
|
||||
Object.entries(value as Record<string, unknown>).forEach(([k, v]) => {
|
||||
paths.push(...collectExpandablePaths(v, `${path}.${k}`, depth + 1));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return paths;
|
||||
}, [maxDepth, getNodeType]);
|
||||
|
||||
const allExpandablePaths = useMemo(() => {
|
||||
return collectExpandablePaths(data, "root");
|
||||
}, [data, collectExpandablePaths]);
|
||||
return collectExpandablePaths(data, "root", maxDepth);
|
||||
}, [data, maxDepth]);
|
||||
|
||||
const expandAll = useCallback(() => {
|
||||
setExpandedPaths(new Set(allExpandablePaths));
|
||||
@@ -109,7 +107,7 @@ function JsonTreeView({ data, className, fontSize = "xs", maxDepth = 10, onExpan
|
||||
}
|
||||
};
|
||||
|
||||
const renderNode = (node: JsonNode, depth: number = 0, isLast: boolean = true): React.ReactNode => {
|
||||
const renderNode = (node: JsonNode, depth: number = 0, _isLast: boolean = true): React.ReactNode => {
|
||||
const { key, value, type, path } = node;
|
||||
const isExpanded = expandedPaths.has(path);
|
||||
const isComplex = type === "object" || type === "array";
|
||||
@@ -239,13 +237,13 @@ function JsonTreeView({ data, className, fontSize = "xs", maxDepth = 10, onExpan
|
||||
|
||||
// Expose expand/collapse functions via useEffect
|
||||
useEffect(() => {
|
||||
if (onExpandAll) {
|
||||
onExpandAll.current = expandAll;
|
||||
if (onExpandAllRef) {
|
||||
onExpandAllRef.current = expandAll;
|
||||
}
|
||||
if (onCollapseAll) {
|
||||
onCollapseAll.current = collapseAll;
|
||||
if (onCollapseAllRef) {
|
||||
onCollapseAllRef.current = collapseAll;
|
||||
}
|
||||
}, [expandAll, collapseAll, onExpandAll, onCollapseAll]);
|
||||
}, [expandAll, collapseAll, onExpandAllRef, onCollapseAllRef]);
|
||||
|
||||
return (
|
||||
<div
|
||||
@@ -264,18 +262,18 @@ function JsonTreeView({ data, className, fontSize = "xs", maxDepth = 10, onExpan
|
||||
);
|
||||
}
|
||||
|
||||
export function JsonTreeViewWrapper({
|
||||
content,
|
||||
className,
|
||||
export function JsonTreeViewWrapper({
|
||||
content,
|
||||
className,
|
||||
fontSize = "xs",
|
||||
onExpandAll,
|
||||
onCollapseAll
|
||||
}: {
|
||||
content: string;
|
||||
className?: string;
|
||||
onExpandAllRef,
|
||||
onCollapseAllRef
|
||||
}: {
|
||||
content: string;
|
||||
className?: string;
|
||||
fontSize?: "xs" | "sm" | "base";
|
||||
onExpandAll?: React.MutableRefObject<(() => void) | undefined>;
|
||||
onCollapseAll?: React.MutableRefObject<(() => void) | undefined>;
|
||||
onExpandAllRef?: React.MutableRefObject<(() => void) | undefined>;
|
||||
onCollapseAllRef?: React.MutableRefObject<(() => void) | undefined>;
|
||||
}) {
|
||||
const parsedData = useMemo(() => {
|
||||
try {
|
||||
@@ -294,12 +292,12 @@ export function JsonTreeViewWrapper({
|
||||
}
|
||||
|
||||
return (
|
||||
<JsonTreeView
|
||||
data={parsedData}
|
||||
className={className}
|
||||
<JsonTreeView
|
||||
data={parsedData}
|
||||
className={className}
|
||||
fontSize={fontSize}
|
||||
onExpandAll={onExpandAll}
|
||||
onCollapseAll={onCollapseAll}
|
||||
onExpandAllRef={onExpandAllRef}
|
||||
onCollapseAllRef={onCollapseAllRef}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ import { PrismaAdapter } from "@auth/prisma-adapter";
|
||||
import { db } from "@/lib/db";
|
||||
import { getConfig } from "@/lib/config";
|
||||
import { initializePlugins, getAuthPlugin } from "@/lib/plugins";
|
||||
import type { User } from "@prisma/client";
|
||||
import type { Adapter, AdapterUser } from "next-auth/adapters";
|
||||
|
||||
// Initialize plugins before use
|
||||
|
||||
@@ -11,7 +11,7 @@ import { z } from "zod";
|
||||
import { db } from "@/lib/db";
|
||||
import { isValidApiKeyFormat } from "@/lib/api-key";
|
||||
import { improvePrompt } from "@/lib/ai/improve-prompt";
|
||||
import { parseSkillFiles, serializeSkillFiles, DEFAULT_SKILL_FILE, DEFAULT_SKILL_CONTENT } from "@/lib/skill-files";
|
||||
import { parseSkillFiles, serializeSkillFiles, DEFAULT_SKILL_FILE } from "@/lib/skill-files";
|
||||
|
||||
interface AuthenticatedUser {
|
||||
id: string;
|
||||
|
||||
Reference in New Issue
Block a user