import { type ClassValue, clsx } from "clsx" // import { toast } from "sonner" import { twMerge } from "tailwind-merge" import fileExtToLang from "./file-extension-to-language.json" import { Sandbox, TFile, TFolder } from "./types" export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)) } export function processFileType(file: string) { const extension = file.split(".").pop() const fileExtToLangMap = fileExtToLang as Record if (extension && fileExtToLangMap[extension]) { return fileExtToLangMap[extension] } return "plaintext" } export function validateName( newName: string, oldName: string, type: "file" | "folder" ) { if (newName === oldName || newName.length === 0) { return { status: false, message: "" } } if ( newName.includes("/") || newName.includes("\\") || newName.includes(" ") || (type === "file" && !newName.includes(".")) || (type === "folder" && newName.includes(".")) ) { return { status: false, message: "Invalid file name." } } return { status: true, message: "" } } export function addNew( name: string, type: "file" | "folder", setFiles: React.Dispatch>, sandboxData: Sandbox ) { if (type === "file") { setFiles((prev) => [ ...prev, { id: `projects/${sandboxData.id}/${name}`, name, type: "file" }, ]) } else { console.log("adding folder") setFiles((prev) => [ ...prev, { id: `projects/${sandboxData.id}/${name}`, name, type: "folder", children: [], }, ]) } } export function debounce void>( func: T, wait: number ): T { let timeout: NodeJS.Timeout | null = null return function (...args: Parameters) { if (timeout) { clearTimeout(timeout) } timeout = setTimeout(() => func(...args), wait) } as T } // Deep merge utility function export const deepMerge = (target: any, source: any) => { const output = { ...target } if (isObject(target) && isObject(source)) { Object.keys(source).forEach((key) => { if (isObject(source[key])) { if (!(key in target)) { Object.assign(output, { [key]: source[key] }) } else { output[key] = deepMerge(target[key], source[key]) } } else { Object.assign(output, { [key]: source[key] }) } }) } return output } const isObject = (item: any) => { return item && typeof item === "object" && !Array.isArray(item) } export function sortFileExplorer( items: (TFile | TFolder)[] ): (TFile | TFolder)[] { return items .sort((a, b) => { // First, sort by type (folders before files) if (a.type !== b.type) { return a.type === "folder" ? -1 : 1 } // Then, sort alphabetically by name return a.name.localeCompare(b.name, undefined, { sensitivity: "base" }) }) .map((item) => { // If it's a folder, recursively sort its children if (item.type === "folder") { return { ...item, children: sortFileExplorer(item.children), } } return item }) }