// Copyright 2024, Command Line // SPDX-License-Identifier: Apache-2.0 import { Button } from "@/element/button"; import { ExpandableMenu, ExpandableMenuItem, ExpandableMenuItemData, ExpandableMenuItemGroup, ExpandableMenuItemGroupTitle, ExpandableMenuItemGroupTitleType, ExpandableMenuItemLeftElement, ExpandableMenuItemRightElement, } from "@/element/expandablemenu"; import { Input } from "@/element/input"; import { Popover, PopoverButton, PopoverContent } from "@/element/popover"; import { makeIconClass } from "@/util/util"; import clsx from "clsx"; import { colord } from "colord"; import { atom, useAtom } from "jotai"; import { OverlayScrollbarsComponent } from "overlayscrollbars-react"; import { memo, useEffect, useRef } from "react"; import WorkspaceSVG from "../asset/workspace.svg"; import "./workspaceswitcher.less"; interface ColorSelectorProps { colors: string[]; selectedColor?: string; onSelect: (color: string) => void; className?: string; } const ColorSelector = memo(({ colors, selectedColor, onSelect, className }: ColorSelectorProps) => { const handleColorClick = (color: string) => { onSelect(color); }; return (
{colors.map((color) => (
handleColorClick(color)} /> ))}
); }); interface IconSelectorProps { icons: string[]; selectedIcon?: string; onSelect: (icon: string) => void; className?: string; } const IconSelector = memo(({ icons, selectedIcon, onSelect, className }: IconSelectorProps) => { const handleIconClick = (icon: string) => { onSelect(icon); }; return (
{icons.map((icon) => { const iconClass = makeIconClass(icon, false); return ( handleIconClick(icon)} /> ); })}
); }); interface ColorAndIconSelectorProps { title: string; icon: string; color: string; focusInput: boolean; onTitleChange: (newTitle: string) => void; onColorChange: (newColor: string) => void; onIconChange: (newIcon: string) => void; onDeleteWorkspace: () => void; } const ColorAndIconSelector = memo( ({ title, icon, color, focusInput, onTitleChange, onColorChange, onIconChange, onDeleteWorkspace, }: ColorAndIconSelectorProps) => { const inputRef = useRef(null); useEffect(() => { if (focusInput && inputRef.current) { inputRef.current.focus(); } }, [focusInput]); return (
); } ); interface WorkspaceDataType { id: string; icon: string; label: string; color: string; isActive: boolean; } // Define the global Jotai atom for menuData const workspaceData: WorkspaceDataType[] = [ { id: "596e76eb-d87d-425e-9f6e-1519069ee446", icon: "", label: "Default", color: "", isActive: false, }, { id: "596e76eb-d87d-425e-9f6e-1519069ee447", icon: "shield-cat", label: "Cat Space", color: "#e91e63", isActive: true, }, { id: "596e76eb-d87d-425e-9f6e-1519069ee448", icon: "paw-simple", label: "Bear Space", color: "#ffc107", isActive: false, }, ]; export const menuDataAtom = atom(workspaceData); const WorkspaceSwitcher = () => { const [menuData, setMenuData] = useAtom(menuDataAtom); const handleTitleChange = (id: string, newTitle: string) => { // This should call a service setMenuData((prevMenuData) => prevMenuData.map((item) => { if (item.id === id) { return { ...item, label: newTitle, }; } return item; }) ); }; const handleColorChange = (id: string, newColor: string) => { // This should call a service setMenuData((prevMenuData) => prevMenuData.map((item) => { if (item.id === id) { return { ...item, color: newColor, }; } return item; }) ); }; const handleIconChange = (id: string, newIcon: string) => { // This should call a service setMenuData((prevMenuData) => prevMenuData.map((item) => { if (item.id === id) { return { ...item, icon: newIcon, }; } return item; }) ); }; const setActiveWorkspace = (id: string) => { // This should call a service setMenuData((prevMenuData) => prevMenuData.map((item) => { if (item.id === id) { return { ...item, isActive: true, }; } return { ...item, isActive: false, }; }) ); }; const handleAddNewWorkspace = () => { // This should call a service const id = `group-${Math.random().toString(36).substr(2, 9)}`; setMenuData((prevMenuData) => { const updatedMenuData = prevMenuData.map((item) => ({ ...item, isActive: false, })); const newWorkspace = { id, icon: "circle", label: "New Workspace", color: "#8bc34a", isActive: true, }; return [...updatedMenuData, newWorkspace]; }); }; const handleDeleteWorkspace = (id: string) => { console.log("got here!!!"); // This should call a service setMenuData((prevMenuData) => { const updatedMenuData = prevMenuData.filter((item) => item.id !== id); console.log("updatedMenuData", updatedMenuData); const isAnyActive = updatedMenuData.some((item) => item.isActive); if (!isAnyActive && updatedMenuData.length > 0) { updatedMenuData[0] = { ...updatedMenuData[0], isActive: true }; } return updatedMenuData; }); }; const activeWorkspace = menuData.find((workspace) => workspace.isActive); const data = menuData.map((item): ExpandableMenuItemData => { const { id, icon, label, color, isActive } = item; const title: ExpandableMenuItemGroupTitleType = { label }; const leftElement = icon ? ( ) : null; title.leftElement = leftElement; title.rightElement = isActive ? : null; if (label === "Default") { return { id, type: "group", title: { leftElement: , label: "Default", rightElement: isActive ? : null, }, }; } return { id, type: "group", title, isOpen: isActive, children: [ { type: "item", content: ({ isOpen }: { isOpen: boolean }) => ( handleTitleChange(id, title)} onColorChange={(color) => handleColorChange(id, color)} onIconChange={(icon) => handleIconChange(id, icon)} onDeleteWorkspace={() => handleDeleteWorkspace(id)} /> ), }, ], }; }); const modWorkspaceColor = activeWorkspace.label === "Default" ? "rgba(0, 0, 0, .2)" : colord(activeWorkspace.color).alpha(0.1).toRgbString(); const renderExpandableMenu = (menuItems: ExpandableMenuItemData[], parentIsOpen?: boolean) => { return menuItems.map((item, index) => { if (item.type === "item") { let contentElement; if (typeof item.content === "function") { contentElement = item.content({ isOpen: parentIsOpen }); } else { contentElement = item.content; } return ( {item.leftElement && ( {item.leftElement} )}
{contentElement}
{item.rightElement && ( {item.rightElement} )}
); } else if (item.type === "group") { return ( setActiveWorkspace(item.id)}>
{item.title.leftElement && ( {item.title.leftElement} )}
{item.title.label}
{item.title.rightElement && ( {item.title.rightElement} )}
{item.children && item.children.length > 0 && renderExpandableMenu(item.children, item.isOpen)}
); } return null; }); }; let workspaceIcon = ( ); if (activeWorkspace.label == "Default") { workspaceIcon = ; } return ( {workspaceIcon} {/* */}
Switch workspace
{renderExpandableMenu(data)}
handleAddNewWorkspace()}>
New workspace
); }; export { WorkspaceSwitcher };