| import React, { createContext, useCallback, useContext, useMemo, useState, type ReactNode } from "react"; | |
| export interface DesktopWindow { | |
| id: string; | |
| title: string; | |
| icon?: ReactNode; | |
| content: ReactNode; | |
| isOpen: boolean; | |
| isMinimized: boolean; | |
| isMaximized: boolean; | |
| position: { x: number; y: number }; | |
| size: { width: number; height: number }; | |
| zIndex: number; | |
| minWidth?: number; | |
| minHeight?: number; | |
| } | |
| interface WindowContextType { | |
| windows: DesktopWindow[]; | |
| activeWindowId: string | null; | |
| openWindow: (title: string, content: ReactNode, options?: Partial<DesktopWindow>) => string; | |
| closeWindow: (id: string) => void; | |
| minimizeWindow: (id: string) => void; | |
| maximizeWindow: (id: string) => void; | |
| restoreWindow: (id: string) => void; | |
| bringToFront: (id: string) => void; | |
| updateWindow: (id: string, updates: Partial<DesktopWindow>) => void; | |
| } | |
| const WindowContext = createContext<WindowContextType | undefined>(undefined); | |
| export function useWindowManager() { | |
| const ctx = useContext(WindowContext); | |
| if (!ctx) throw new Error("useWindowManager must be used within WindowContainer"); | |
| return ctx; | |
| } | |
| export function WindowContainer({ children }: { children: ReactNode }) { | |
| const [windows, setWindows] = useState<DesktopWindow[]>([]); | |
| const [activeWindowId, setActiveWindowId] = useState<string | null>(null); | |
| const [nextZIndex, setNextZIndex] = useState(10); | |
| const openWindow = useCallback((title: string, content: ReactNode, options?: Partial<DesktopWindow>) => { | |
| const id = globalThis.crypto?.randomUUID?.() ?? `${Date.now()}-${Math.random().toString(36).slice(2)}`; | |
| const basePosition = { x: 100 + windows.length * 30, y: 100 + windows.length * 30 }; | |
| const newWindow: DesktopWindow = { | |
| id, | |
| title, | |
| content, | |
| isOpen: true, | |
| isMinimized: false, | |
| isMaximized: false, | |
| position: options?.position ?? basePosition, | |
| size: options?.size ?? { width: 800, height: 600 }, | |
| zIndex: nextZIndex, | |
| minWidth: options?.minWidth ?? 400, | |
| minHeight: options?.minHeight ?? 300, | |
| icon: options?.icon, | |
| }; | |
| setWindows((prev) => [...prev, newWindow]); | |
| setActiveWindowId(id); | |
| setNextZIndex((prev) => prev + 1); | |
| return id; | |
| }, [nextZIndex, windows.length]); | |
| const closeWindow = useCallback((id: string) => { | |
| setWindows((prev) => prev.filter((w) => w.id !== id)); | |
| setActiveWindowId((prev) => (prev === id ? null : prev)); | |
| }, []); | |
| const minimizeWindow = useCallback((id: string) => { | |
| setWindows((prev) => prev.map((w) => (w.id === id ? { ...w, isMinimized: true } : w))); | |
| }, []); | |
| const maximizeWindow = useCallback((id: string) => { | |
| setWindows((prev) => prev.map((w) => (w.id === id ? { ...w, isMaximized: true, isMinimized: false } : w))); | |
| }, []); | |
| const restoreWindow = useCallback((id: string) => { | |
| setWindows((prev) => prev.map((w) => (w.id === id ? { ...w, isMaximized: false, isMinimized: false } : w))); | |
| }, []); | |
| const bringToFront = useCallback((id: string) => { | |
| setWindows((prev) => prev.map((w) => (w.id === id ? { ...w, zIndex: nextZIndex } : w))); | |
| setActiveWindowId(id); | |
| setNextZIndex((prev) => prev + 1); | |
| }, [nextZIndex]); | |
| const updateWindow = useCallback((id: string, updates: Partial<DesktopWindow>) => { | |
| setWindows((prev) => prev.map((w) => (w.id === id ? { ...w, ...updates } : w))); | |
| }, []); | |
| const value = useMemo( | |
| () => ({ | |
| windows, | |
| activeWindowId, | |
| openWindow, | |
| closeWindow, | |
| minimizeWindow, | |
| maximizeWindow, | |
| restoreWindow, | |
| bringToFront, | |
| updateWindow, | |
| }), | |
| [windows, activeWindowId, openWindow, closeWindow, minimizeWindow, maximizeWindow, restoreWindow, bringToFront, updateWindow] | |
| ); | |
| return <WindowContext.Provider value={value}>{children}</WindowContext.Provider>; | |
| } | |
Xet Storage Details
- Size:
- 3.84 kB
- Xet hash:
- f4479b8b4743130e4befbea5c267b33a3a2323d91218208918d52b8289a0d6ec
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.