diff --git a/theme-test.tsx b/theme-test.tsx new file mode 100644 index 00000000..16559bf7 --- /dev/null +++ b/theme-test.tsx @@ -0,0 +1,285 @@ +import React, { useState, useEffect, useCallback, useMemo } from "react" +import { ComponentType, FC, ReactNode, JSX } from "react" + +// Interface definitions +interface User { + id: number + name: string + email?: string + readonly createdAt: Date + active: boolean +} + +type Theme = "light" | "dark" | "auto" +type Status = "pending" | "loading" | "success" | "error" + +// Generic function with constraints +function createRepository(items: T[]): Repository { + return new Repository(items) +} + +// Class definition +class Repository { + private items: T[] + protected cache: Map + + constructor(items: T[] = []) { + this.items = items + this.cache = new Map() + } + + public find(id: number): T | undefined { + return this.items.find((item) => item.id === id) + } + + public async findAll(): Promise { + return this.items + } + + get count(): number { + return this.items.length + } +} + +// Enum definition +enum LogLevel { + DEBUG = 0, + INFO = 1, + WARN = 2, + ERROR = 3, +} + +// Constants +const API_URL = "https://api.example.com" +const MAX_RETRIES = 3 +const DEFAULT_TIMEOUT = 5000 + +// Regular expressions +const EMAIL_REGEX = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/ +const PHONE_REGEX = /^\+?1?-?\.?\s?\(?(\d{3})\)?[-.\s]?(\d{3})[-.\s]?(\d{4})$/ + +// Template literals +const greeting = `Hello, ${user.name}!` +const sql = ` + SELECT * FROM users + WHERE active = true + AND created_at > '${new Date().toISOString()}' +` + +// Arrow functions +const debounce = any>( + func: T, + wait: number, +): ((...args: Parameters) => void) => { + let timeout: NodeJS.Timeout + return (...args: Parameters) => { + clearTimeout(timeout) + timeout = setTimeout(() => func(...args), wait) + } +} + +// Async function +async function fetchUserData(userId: number): Promise { + try { + const response = await fetch(`${API_URL}/users/${userId}`) + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`) + } + return await response.json() + } catch (error) { + console.error("Failed to fetch user data:", error) + throw error + } +} + +// React component with various patterns +const ThemeProvider: FC<{ children: ReactNode; theme?: Theme }> = ({ + children, + theme = "auto", +}) => { + const [currentTheme, setCurrentTheme] = useState(theme) + const [status, setStatus] = useState("pending") + + useEffect(() => { + const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)") + const handleChange = (e: MediaQueryListEvent) => { + setCurrentTheme(e.matches ? "dark" : "light") + } + + mediaQuery.addEventListener("change", handleChange) + return () => mediaQuery.removeEventListener("change", handleChange) + }, []) + + const contextValue = useMemo( + () => ({ + theme: currentTheme, + setTheme: setCurrentTheme, + toggleTheme: () => setCurrentTheme((prev) => (prev === "light" ? "dark" : "light")), + }), + [currentTheme], + ) + + return ( + +
+ {children} +
+
+ ) +} + +// Higher-order component +function withLogging

(Component: ComponentType

): ComponentType

{ + return function LoggedComponent(props: P) { + console.log("Rendering component:", Component.name) + return + } +} + +// Custom hook +function useLocalStorage(key: string, initialValue: T): [T, (value: T) => void] { + const [storedValue, setStoredValue] = useState(() => { + try { + const item = window.localStorage.getItem(key) + return item ? JSON.parse(item) : initialValue + } catch (error) { + console.warn(`Error reading localStorage key "${key}":`, error) + return initialValue + } + }) + + const setValue = useCallback( + (value: T) => { + try { + setStoredValue(value) + window.localStorage.setItem(key, JSON.stringify(value)) + } catch (error) { + console.warn(`Error setting localStorage key "${key}":`, error) + } + }, + [key], + ) + + return [storedValue, setValue] +} + +// JSX component with various elements +const UserProfile: FC<{ user: User; onUpdate?: (user: User) => void }> = ({ user, onUpdate }) => { + const [isEditing, setIsEditing] = useState(false) + const [formData, setFormData] = useState(user) + const [errors, setErrors] = useState>({}) + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault() + + // Validation + if (!formData.name.trim()) { + setErrors({ name: "Name is required" }) + return + } + + if (formData.email && !EMAIL_REGEX.test(formData.email)) { + setErrors({ email: "Invalid email format" }) + return + } + + try { + setStatus("loading") + await onUpdate?.(formData) + setStatus("success") + setIsEditing(false) + } catch (error) { + setStatus("error") + setErrors({ submit: "Failed to update profile" }) + } + } + + return ( +

+
+

{user.name}

+ + {user.active ? "Active" : "Inactive"} + +
+ + {isEditing ? ( +
+
+ + setFormData({ ...formData, name: e.target.value })} + className={errors.name ? "error" : ""} + placeholder="Enter your name" + required + /> + {errors.name && {errors.name}} +
+ +
+ + setFormData({ ...formData, email: e.target.value })} + className={errors.email ? "error" : ""} + placeholder="user@example.com" + /> + {errors.email && {errors.email}} +
+ +
+ + +
+ + {errors.submit &&
{errors.submit}
} +
+ ) : ( +
+

+ ID: {user.id} +

+

+ Email: {user.email || "Not provided"} +

+

+ Member since: {user.createdAt.toLocaleDateString()} +

+ + +
+ )} +
+ ) +} + +// Export statements +export { + User, + Theme, + Status, + LogLevel, + Repository, + ThemeProvider, + UserProfile, + fetchUserData, + useLocalStorage, + withLogging, + debounce, +} + +export default ThemeProvider + +// Type exports +export type { User as UserType, ComponentType as ReactComponentType }