diff --git a/apps/fronted/src/components/editor/SidePanel.tsx b/apps/fronted/src/components/editor/SidePanel.tsx index 32dc66d..e5dd3f1 100644 --- a/apps/fronted/src/components/editor/SidePanel.tsx +++ b/apps/fronted/src/components/editor/SidePanel.tsx @@ -1,18 +1,8 @@ "use client"; - -import { motion, Reorder } from "framer-motion"; -import { - GripVertical, - Eye, - EyeOff, - Layout, - Type, - SpaceIcon, - Palette, - Plus, - Trash2, -} from "lucide-react"; -import { useResumeStore } from "@/store/useResumeStore"; +import { useMemo } from "react"; +import { motion } from "framer-motion"; +import { Layout, Type, SpaceIcon, Palette } from "lucide-react"; +import debounce from "lodash/debounce"; import { Select, SelectContent, @@ -22,12 +12,12 @@ import { } from "@/components/ui/select"; import { Slider } from "@/components/ui/slider"; import { Label } from "@/components/ui/label"; +import { Switch } from "@/components/ui/switch"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; +import LayoutSetting from "./layout/LayoutSetting"; +import { useResumeStore } from "@/store/useResumeStore"; import { cn } from "@/lib/utils"; import { THEME_COLORS } from "@/types/resume"; -import debounce from "lodash/debounce"; -import { useMemo } from "react"; -import { Switch } from "../ui/switch"; const fontOptions = [ { value: "sans", label: "无衬线体" }, @@ -133,128 +123,15 @@ export function SidePanel() { >
- {menuSections - .filter((item) => item.id === "basic") - .map((item) => ( -
-
- - {item.icon} - - setActiveSection(item.id)} - > - {item.title} - -
-
- ))} + - - {menuSections - .filter((item) => item.id !== "basic") - .map((item) => ( - -
- - - {item.icon} - - setActiveSection(item.id)} - > - {item.title} - - toggleSectionVisibility(item.id)} - className={cn( - "p-1.5 rounded-md", - "dark:hover:bg-neutral-700 dark:text-neutral-300", - "hover:bg-gray-100 text-gray-600" - )} - > - {item.enabled ? ( - - ) : ( - - )} - - - { - updateMenuSections( - menuSections.filter( - (section) => section.id !== item.id - ) - ); - setActiveSection( - menuSections[ - menuSections.findIndex((s) => s.id === item.id) - 1 - ].id - ); - }} - className={cn( - "p-1.5 rounded-md text-primary", - "dark:hover:bg-neutral-700 dark:text-neutral-300", - "hover:bg-gray-100 text-gray-600" - )} - > - - -
-
- ))} -
void; + toggleSectionVisibility: (id: string) => void; + updateMenuSections: (sections: MenuSection[]) => void; + menuSections: MenuSection[]; +} + +const LayoutItem = ({ + item, + isBasic = false, + activeSection, + setActiveSection, + toggleSectionVisibility, + updateMenuSections, + menuSections, +}: LayoutItemProps) => { + const dragControls = useDragControls(); + + if (isBasic) { + return ( +
+
+ + {item.icon} + + setActiveSection(item.id)} + > + {item.title} + +
+
+ ); + } + + return ( + +
{ + dragControls.start(event); + }} + className={cn( + "w-8 flex items-center justify-center touch-none shrink-0", + "border-gray-100 dark:border-neutral-800", + "cursor-grab hover:bg-gray-50 dark:hover:bg-neutral-800/50" + )} + > + +
+ +
+
+ + {item.icon} + + setActiveSection(item.id)} + > + {item.title} + + toggleSectionVisibility(item.id)} + className={cn( + "p-1.5 rounded-md mr-2", + "dark:hover:bg-neutral-700 dark:text-neutral-300", + "hover:bg-gray-100 text-gray-600" + )} + > + {item.enabled ? ( + + ) : ( + + )} + + + { + updateMenuSections( + menuSections.filter((section) => section.id !== item.id) + ); + setActiveSection( + menuSections[ + menuSections.findIndex((s) => s.id === item.id) - 1 + ].id + ); + }} + className={cn( + "p-1.5 rounded-md text-primary", + "dark:hover:bg-neutral-700 dark:text-neutral-300", + "hover:bg-gray-100 text-gray-600" + )} + > + + +
+
+
+ ); +}; + +export default LayoutItem; diff --git a/apps/fronted/src/components/editor/layout/LayoutSetting.tsx b/apps/fronted/src/components/editor/layout/LayoutSetting.tsx new file mode 100644 index 0000000..70daf89 --- /dev/null +++ b/apps/fronted/src/components/editor/layout/LayoutSetting.tsx @@ -0,0 +1,68 @@ +"use client"; +import { Reorder } from "framer-motion"; +import { MenuSection } from "@/types/resume"; +import LayoutItem from "./LayoutItem"; + +interface LayoutPanelProps { + menuSections: MenuSection[]; + activeSection: string; + setActiveSection: (id: string) => void; + toggleSectionVisibility: (id: string) => void; + updateMenuSections: (sections: MenuSection[]) => void; + reorderSections: (sections: MenuSection[]) => void; +} + +const LayoutSetting = ({ + menuSections, + activeSection, + setActiveSection, + toggleSectionVisibility, + updateMenuSections, + reorderSections, +}: LayoutPanelProps) => { + const basicSection = menuSections.find((item) => item.id === "basic"); + const draggableSections = menuSections.filter((item) => item.id !== "basic"); + + return ( +
+ {basicSection && ( + + )} + + { + const updatedSections = [ + ...menuSections.filter((item) => item.id === "basic"), + ...newOrder, + ]; + reorderSections(updatedSections); + }} + className="space-y-2" + > + {draggableSections.map((item) => ( + + ))} + +
+ ); +}; + +export default LayoutSetting;