From 0c19c64a17b822034ce6fa8097dfc75fbdea5e1b Mon Sep 17 00:00:00 2001 From: James Pine Date: Thu, 26 Mar 2026 22:23:29 -0700 Subject: [PATCH] ui --- .../SpacesSidebar/SpaceSwitcher.tsx | 52 +- .../src/components/SpacesSidebar/index.tsx | 967 ++++++++++-------- .../interface/src/routes/explorer/Sidebar.tsx | 363 +++---- 3 files changed, 754 insertions(+), 628 deletions(-) diff --git a/packages/interface/src/components/SpacesSidebar/SpaceSwitcher.tsx b/packages/interface/src/components/SpacesSidebar/SpaceSwitcher.tsx index fc91ae265..7414e7f42 100644 --- a/packages/interface/src/components/SpacesSidebar/SpaceSwitcher.tsx +++ b/packages/interface/src/components/SpacesSidebar/SpaceSwitcher.tsx @@ -1,8 +1,8 @@ +import {CaretDown, GearSix, Plus} from '@phosphor-icons/react'; +import type {Space} from '@sd/ts-client'; +import {DropdownMenu, SelectPill} from '@spaceui/primitives'; import clsx from 'clsx'; -import { CaretDown, Plus, GearSix } from '@phosphor-icons/react'; -import { DropdownMenu } from '@spaceui/primitives'; -import type { Space } from '@sd/ts-client'; -import { useCreateSpaceDialog } from './CreateSpaceModal'; +import {useCreateSpaceDialog} from './CreateSpaceModal'; interface SpaceSwitcherProps { spaces: Space[] | undefined; @@ -10,68 +10,60 @@ interface SpaceSwitcherProps { onSwitch: (spaceId: string) => void; } -export function SpaceSwitcher({ spaces, currentSpace, onSwitch }: SpaceSwitcherProps) { +export function SpaceSwitcher({ + spaces, + currentSpace, + onSwitch +}: SpaceSwitcherProps) { const createSpaceDialog = useCreateSpaceDialog; return ( - + - + {spaces && spaces.length > 1 ? spaces.map((space) => ( onSwitch(space.id)} className={clsx( - "px-2 py-1 text-sm rounded-md", + 'rounded-md px-2 py-1 text-sm', space.id === currentSpace?.id - ? "bg-accent text-white" - : "text-sidebar-ink hover:bg-sidebar-selected" + ? 'bg-accent text-white' + : 'text-sidebar-ink hover:bg-sidebar-selected' )} >
{space.name}
- )) + )) : null} {spaces && spaces.length > 1 && ( )} createSpaceDialog()} - className="px-2 py-1 text-sm rounded-md hover:bg-sidebar-selected text-sidebar-ink font-medium" + className="hover:bg-sidebar-selected text-sidebar-ink rounded-md px-2 py-1 text-sm font-medium" > New Space - + Space Settings diff --git a/packages/interface/src/components/SpacesSidebar/index.tsx b/packages/interface/src/components/SpacesSidebar/index.tsx index 140813a5e..169d0ecf4 100644 --- a/packages/interface/src/components/SpacesSidebar/index.tsx +++ b/packages/interface/src/components/SpacesSidebar/index.tsx @@ -1,476 +1,591 @@ -import { useState, useEffect, memo } from "react"; -import { GearSix, Palette, ArrowsClockwise, ListBullets, CircleNotch, ArrowsOut, FunnelSimple } from "@phosphor-icons/react"; -import { useSidebarStore, useLibraryMutation } from "@sd/ts-client"; -import type { SpaceGroup as SpaceGroupType, SpaceItem as SpaceItemType } from "@sd/ts-client"; -import { Popover, CircleButton, usePopover } from "@spaceui/primitives"; -import { useSpaces, useSpaceLayout } from "./hooks/useSpaces"; -import { SpaceSwitcher } from "./SpaceSwitcher"; -import { SpaceGroup } from "./SpaceGroup"; -import { SpaceItem } from "./SpaceItem"; -import { AddGroupButton } from "./AddGroupButton"; -import { SpaceCustomizationPanel } from "./SpaceCustomizationPanel"; -import { useSpacedriveClient } from "../../contexts/SpacedriveContext"; -import { useLibraries } from "../../hooks/useLibraries"; -import { usePlatform } from "../../contexts/PlatformContext"; -import { useJobsContext } from "../JobManager/hooks/JobsContext"; -import { useSyncCount } from "../SyncMonitor/hooks/useSyncCount"; -import { useSyncMonitor } from "../SyncMonitor/hooks/useSyncMonitor"; -import { PeerList } from "../SyncMonitor/components/PeerList"; -import { ActivityFeed } from "../SyncMonitor/components/ActivityFeed"; -import { JobList } from "../JobManager/components/JobList"; -import { motion } from "framer-motion"; -import { CARD_HEIGHT } from "../JobManager/types"; -import clsx from "clsx"; -import { useDroppable, useDndContext } from "@dnd-kit/core"; -import { SortableContext, verticalListSortingStrategy, useSortable } from "@dnd-kit/sortable"; -import { CSS } from "@dnd-kit/utilities"; -import { useNavigate } from "react-router-dom"; +import {useDndContext, useDroppable} from '@dnd-kit/core'; +import { + SortableContext, + useSortable, + verticalListSortingStrategy +} from '@dnd-kit/sortable'; +import {CSS} from '@dnd-kit/utilities'; +import { + ArrowsClockwise, + ArrowsOut, + CircleNotch, + FunnelSimple, + GearSix, + ListBullets, + Palette +} from '@phosphor-icons/react'; +import {useLibraryMutation, useSidebarStore} from '@sd/ts-client'; +import type { + SpaceGroup as SpaceGroupType, + SpaceItem as SpaceItemType +} from '@sd/ts-client'; +import {CircleButton, Popover, usePopover} from '@spaceui/primitives'; +import clsx from 'clsx'; +import {motion} from 'framer-motion'; +import {memo, useEffect, useState} from 'react'; +import {useNavigate} from 'react-router-dom'; +import {usePlatform} from '../../contexts/PlatformContext'; +import {useSpacedriveClient} from '../../contexts/SpacedriveContext'; +import {useLibraries} from '../../hooks/useLibraries'; +import {JobList} from '../JobManager/components/JobList'; +import {useJobsContext} from '../JobManager/hooks/JobsContext'; +import {CARD_HEIGHT} from '../JobManager/types'; +import {ActivityFeed} from '../SyncMonitor/components/ActivityFeed'; +import {PeerList} from '../SyncMonitor/components/PeerList'; +import {useSyncCount} from '../SyncMonitor/hooks/useSyncCount'; +import {useSyncMonitor} from '../SyncMonitor/hooks/useSyncMonitor'; +import {AddGroupButton} from './AddGroupButton'; +import {useSpaceLayout, useSpaces} from './hooks/useSpaces'; +import {SpaceCustomizationPanel} from './SpaceCustomizationPanel'; +import {SpaceGroup} from './SpaceGroup'; +import {SpaceItem} from './SpaceItem'; +import {SpaceSwitcher} from './SpaceSwitcher'; // Wrapper that adds a space-level drop zone before each group and makes it sortable function SpaceGroupWithDropZone({ - group, - items, - spaceId, - isFirst, + group, + items, + spaceId, + isFirst }: { - group: SpaceGroupType; - items: SpaceItemType[]; - spaceId?: string; - isFirst: boolean; + group: SpaceGroupType; + items: SpaceItemType[]; + spaceId?: string; + isFirst: boolean; }) { - const { active } = useDndContext(); - - // Disable drop zone when dragging groups or space items (they have 'label' in their data) - // This allows sortable collision detection to work for reordering - const isDraggingSortableItem = active?.data?.current?.label != null; - - const { setNodeRef: setDropRef, isOver } = useDroppable({ - id: `space-root-before-${group.id}`, - disabled: !spaceId || isDraggingSortableItem, - data: { - action: 'add-to-space', - spaceId, - groupId: null, - }, - }); + const {active} = useDndContext(); - // Sortable for group reordering - const { - attributes, - listeners, - setNodeRef: setSortableRef, - transform, - transition, - isDragging, - setActivatorNodeRef, - } = useSortable({ - id: group.id, - data: { - label: group.name, - }, - }); + // Disable drop zone when dragging groups or space items (they have 'label' in their data) + // This allows sortable collision detection to work for reordering + const isDraggingSortableItem = active?.data?.current?.label != null; - const style = { - transform: CSS.Transform.toString(transform), - transition, - }; + const {setNodeRef: setDropRef, isOver} = useDroppable({ + id: `space-root-before-${group.id}`, + disabled: !spaceId || isDraggingSortableItem, + data: { + action: 'add-to-space', + spaceId, + groupId: null + } + }); - return ( -
- {/* Drop zone before this group (for adding root-level items) */} -
- {isOver && !isDragging && !isDraggingSortableItem && ( -
- )} -
- -
- ); + // Sortable for group reordering + const { + attributes, + listeners, + setNodeRef: setSortableRef, + transform, + transition, + isDragging, + setActivatorNodeRef + } = useSortable({ + id: group.id, + data: { + label: group.name + } + }); + + const style = { + transform: CSS.Transform.toString(transform), + transition + }; + + return ( +
+ {/* Drop zone before this group (for adding root-level items) */} +
+ {isOver && !isDragging && !isDraggingSortableItem && ( +
+ )} +
+ +
+ ); } // Sync Monitor Button with Popover const SyncButton = memo(function SyncButton() { - const popover = usePopover(); - const navigate = useNavigate(); - const [showActivityFeed, setShowActivityFeed] = useState(false); - const { onlinePeerCount, isSyncing } = useSyncCount(); - const sync = useSyncMonitor(); + const popover = usePopover(); + const navigate = useNavigate(); + const [showActivityFeed, setShowActivityFeed] = useState(false); + const {onlinePeerCount, isSyncing} = useSyncCount(); + const sync = useSyncMonitor(); - useEffect(() => { - if (popover.open) { - setShowActivityFeed(false); - } - }, [popover.open]); + useEffect(() => { + if (popover.open) { + setShowActivityFeed(false); + } + }, [popover.open]); - const getStateColor = (state: string) => { - switch (state) { - case "Ready": - return "bg-green-500"; - case "Backfilling": - return "bg-yellow-500"; - case "CatchingUp": - return "bg-accent"; - case "Uninitialized": - return "bg-ink-faint"; - case "Paused": - return "bg-ink-dull"; - default: - return "bg-ink-faint"; - } - }; + const getStateColor = (state: string) => { + switch (state) { + case 'Ready': + return 'bg-green-500'; + case 'Backfilling': + return 'bg-yellow-500'; + case 'CatchingUp': + return 'bg-accent'; + case 'Uninitialized': + return 'bg-ink-faint'; + case 'Paused': + return 'bg-ink-dull'; + default: + return 'bg-ink-faint'; + } + }; - return ( - - - - isSyncing ? ( - - ) : ( - - ) - } - title="Sync Monitor" - /> - - -
-

Sync Monitor

+ return ( + + + + isSyncing ? ( + + ) : ( + + ) + } + title="Sync Monitor" + /> + + +
+

+ Sync Monitor +

-
- {onlinePeerCount > 0 && ( - - {onlinePeerCount} {onlinePeerCount === 1 ? "peer" : "peers"} online - - )} +
+ {onlinePeerCount > 0 && ( + + {onlinePeerCount}{' '} + {onlinePeerCount === 1 ? 'peer' : 'peers'}{' '} + online + + )} - navigate("/sync")} - title="Open full sync monitor" - /> + navigate('/sync')} + title="Open full sync monitor" + /> - setShowActivityFeed(!showActivityFeed)} - title={showActivityFeed ? "Show peers" : "Show activity feed"} - /> -
-
+ + setShowActivityFeed(!showActivityFeed) + } + title={ + showActivityFeed + ? 'Show peers' + : 'Show activity feed' + } + /> +
+
- {popover.open && ( - <> -
-
-
- {sync.currentState} -
-
- - {showActivityFeed ? ( - - ) : ( - - )} - - - )} - - - ); + {popover.open && ( + <> +
+
+
+ + {sync.currentState} + +
+
+ + {showActivityFeed ? ( + + ) : ( + + )} + + + )} + + + ); }); // Jobs Button with Popover -const JobsButton = memo(function JobsButton({ - activeJobCount, - hasRunningJobs, - jobs, - pause, - resume, - cancel, - getSpeedHistory, - navigate -}: { - activeJobCount: number; - hasRunningJobs: boolean; - jobs: any[]; - pause: (jobId: string) => Promise; - resume: (jobId: string) => Promise; - cancel: (jobId: string) => Promise; - getSpeedHistory: (jobId: string) => any[]; - navigate: any; -}) { - const popover = usePopover(); - const [showOnlyRunning, setShowOnlyRunning] = useState(true); +const JobsButton = memo( + function JobsButton({ + activeJobCount, + hasRunningJobs, + jobs, + pause, + resume, + cancel, + getSpeedHistory, + navigate + }: { + activeJobCount: number; + hasRunningJobs: boolean; + jobs: any[]; + pause: (jobId: string) => Promise; + resume: (jobId: string) => Promise; + cancel: (jobId: string) => Promise; + getSpeedHistory: (jobId: string) => any[]; + navigate: any; + }) { + const popover = usePopover(); + const [showOnlyRunning, setShowOnlyRunning] = useState(true); - useEffect(() => { - if (popover.open) { - setShowOnlyRunning(true); - } - }, [popover.open]); + useEffect(() => { + if (popover.open) { + setShowOnlyRunning(true); + } + }, [popover.open]); - const filteredJobs = showOnlyRunning - ? jobs.filter((job) => job.status === "running" || job.status === "paused") - : jobs; + const filteredJobs = showOnlyRunning + ? jobs.filter( + (job) => job.status === 'running' || job.status === 'paused' + ) + : jobs; - return ( - - - - hasRunningJobs ? ( - - ) : ( - - ) - } - title="Job Manager" - /> - - -
-

Job Manager

+ return ( + + + + hasRunningJobs ? ( + + ) : ( + + ) + } + title="Job Manager" + /> + + +
+

+ Job Manager +

-
- {activeJobCount > 0 && ( - {activeJobCount} active - )} +
+ {activeJobCount > 0 && ( + + {activeJobCount} active + + )} - navigate("/jobs")} - title="Open full jobs screen" - /> + navigate('/jobs')} + title="Open full jobs screen" + /> - setShowOnlyRunning(!showOnlyRunning)} - title={showOnlyRunning ? "Show all jobs" : "Show only active jobs"} - /> -
-
+ + setShowOnlyRunning(!showOnlyRunning) + } + title={ + showOnlyRunning + ? 'Show all jobs' + : 'Show only active jobs' + } + /> +
+
- {popover.open && ( - - - - )} -
-
- ); -}, (prevProps, nextProps) => { - // Only re-render if these specific values change - return ( - prevProps.activeJobCount === nextProps.activeJobCount && - prevProps.hasRunningJobs === nextProps.hasRunningJobs - ); -}); + {popover.open && ( + + + + )} + + + ); + }, + (prevProps, nextProps) => { + // Only re-render if these specific values change + return ( + prevProps.activeJobCount === nextProps.activeJobCount && + prevProps.hasRunningJobs === nextProps.hasRunningJobs + ); + } +); interface SpacesSidebarProps { - isPreviewActive?: boolean; + isPreviewActive?: boolean; } -export function SpacesSidebar({ isPreviewActive = false }: SpacesSidebarProps) { - const client = useSpacedriveClient(); - const platform = usePlatform(); - const navigate = useNavigate(); - const { data: libraries } = useLibraries(); - const [currentLibraryId, setCurrentLibraryId] = useState( - () => client.getCurrentLibraryId(), - ); - const [customizePanelOpen, setCustomizePanelOpen] = useState(false); +export function SpacesSidebar({isPreviewActive = false}: SpacesSidebarProps) { + const client = useSpacedriveClient(); + const platform = usePlatform(); + const navigate = useNavigate(); + const {data: libraries} = useLibraries(); + const [currentLibraryId, setCurrentLibraryId] = useState( + () => client.getCurrentLibraryId() + ); + const [customizePanelOpen, setCustomizePanelOpen] = useState(false); - // Get sync and job status for icons - const { onlinePeerCount, isSyncing } = useSyncCount(); - const { activeJobCount, hasRunningJobs, jobs, pause, resume, cancel, getSpeedHistory } = useJobsContext(); + // Get sync and job status for icons + const {onlinePeerCount, isSyncing} = useSyncCount(); + const { + activeJobCount, + hasRunningJobs, + jobs, + pause, + resume, + cancel, + getSpeedHistory + } = useJobsContext(); - const { currentSpaceId, setCurrentSpace } = useSidebarStore(); - const { data: spacesData } = useSpaces(); - const spaces = spacesData?.spaces; + const {currentSpaceId, setCurrentSpace} = useSidebarStore(); + const {data: spacesData} = useSpaces(); + const spaces = spacesData?.spaces; - // Listen for library changes from client and update local state - useEffect(() => { - const handleLibraryChange = (newLibraryId: string) => { - setCurrentLibraryId(newLibraryId); - }; + // Listen for library changes from client and update local state + useEffect(() => { + const handleLibraryChange = (newLibraryId: string) => { + setCurrentLibraryId(newLibraryId); + }; - client.on("library-changed", handleLibraryChange); - return () => { - client.off("library-changed", handleLibraryChange); - }; - }, [client]); + client.on('library-changed', handleLibraryChange); + return () => { + client.off('library-changed', handleLibraryChange); + }; + }, [client]); - // Auto-select first library on mount if none selected - useEffect(() => { - if (libraries && libraries.length > 0 && !currentLibraryId) { - const firstLib = libraries[0]; + // Auto-select first library on mount if none selected + useEffect(() => { + if (libraries && libraries.length > 0 && !currentLibraryId) { + const firstLib = libraries[0]; - // Set library ID via platform (syncs to all windows on Tauri) - if (platform.setCurrentLibraryId) { - platform.setCurrentLibraryId(firstLib.id).catch((err) => - console.error("Failed to set library ID:", err), - ); - } else { - // Web fallback - just update client - client.setCurrentLibrary(firstLib.id); - } - } - }, [libraries, currentLibraryId, client, platform]); + // Set library ID via platform (syncs to all windows on Tauri) + if (platform.setCurrentLibraryId) { + platform + .setCurrentLibraryId(firstLib.id) + .catch((err) => + console.error('Failed to set library ID:', err) + ); + } else { + // Web fallback - just update client + client.setCurrentLibrary(firstLib.id); + } + } + }, [libraries, currentLibraryId, client, platform]); - // Auto-select first space if none selected - const currentSpace = - spaces?.find((s) => s.id === currentSpaceId) ?? spaces?.[0]; + // Auto-select first space if none selected + const currentSpace = + spaces?.find((s) => s.id === currentSpaceId) ?? spaces?.[0]; - useEffect(() => { - if (currentSpace && currentSpace.id !== currentSpaceId) { - setCurrentSpace(currentSpace.id); - } - }, [currentSpace, currentSpaceId, setCurrentSpace]); + useEffect(() => { + if (currentSpace && currentSpace.id !== currentSpaceId) { + setCurrentSpace(currentSpace.id); + } + }, [currentSpace, currentSpaceId, setCurrentSpace]); - const { data: layout } = useSpaceLayout(currentSpace?.id ?? null); + const {data: layout} = useSpaceLayout(currentSpace?.id ?? null); - const addItem = useLibraryMutation("spaces.add_item"); + const addItem = useLibraryMutation('spaces.add_item'); - return ( -
-
- +
- {/* Customization Panel */} - setCustomizePanelOpen(false)} - spaceId={currentSpace?.id ?? null} - /> -
- ); + {/* Customization Panel */} + setCustomizePanelOpen(false)} + spaceId={currentSpace?.id ?? null} + /> +
+ ); } diff --git a/packages/interface/src/routes/explorer/Sidebar.tsx b/packages/interface/src/routes/explorer/Sidebar.tsx index 66ee4fdff..d776e8f8b 100644 --- a/packages/interface/src/routes/explorer/Sidebar.tsx +++ b/packages/interface/src/routes/explorer/Sidebar.tsx @@ -1,189 +1,208 @@ -import { useState, useEffect } from "react"; -import { useNavigate, useLocation } from "react-router-dom"; -import clsx from "clsx"; import { - House, - Clock, - Heart, - Tag, - Network, - GearSix, - Planet, - CaretDown, - Plus, -} from "@phosphor-icons/react"; -import { DropdownMenu } from "@spaceui/primitives"; -import { useSpacedriveClient } from "../../contexts/SpacedriveContext"; -import { useLibraries } from "../../hooks/useLibraries"; -import { usePlatform } from "../../contexts/PlatformContext"; -import { LocationsSection } from "./components/LocationsSection"; -import { Section } from "./components/Section"; -import { SidebarItem } from "./components/SidebarItem"; -import { JobManagerPopover } from "../../components/JobManager"; -import { SyncMonitorPopover } from "../../components/SyncMonitor"; + CaretDown, + Clock, + GearSix, + Heart, + House, + Network, + Planet, + Plus, + Tag +} from '@phosphor-icons/react'; +import {DropdownMenu} from '@spaceui/primitives'; +import clsx from 'clsx'; +import {useEffect, useState} from 'react'; +import {useLocation, useNavigate} from 'react-router-dom'; +import {JobManagerPopover} from '../../components/JobManager'; +import {SyncMonitorPopover} from '../../components/SyncMonitor'; +import {usePlatform} from '../../contexts/PlatformContext'; +import {useSpacedriveClient} from '../../contexts/SpacedriveContext'; +import {useLibraries} from '../../hooks/useLibraries'; +import {LocationsSection} from './components/LocationsSection'; +import {Section} from './components/Section'; +import {SidebarItem} from './components/SidebarItem'; export function Sidebar() { - const client = useSpacedriveClient(); - const platform = usePlatform(); - const { data: libraries } = useLibraries(); - const navigate = useNavigate(); - const location = useLocation(); - const [currentLibraryId, setCurrentLibraryId] = useState( - () => client.getCurrentLibraryId(), - ); + const client = useSpacedriveClient(); + const platform = usePlatform(); + const {data: libraries} = useLibraries(); + const navigate = useNavigate(); + const location = useLocation(); + const [currentLibraryId, setCurrentLibraryId] = useState( + () => client.getCurrentLibraryId() + ); - const isActive = (path: string) => location.pathname === path; + const isActive = (path: string) => location.pathname === path; - // Listen for library changes from client and update local state - useEffect(() => { - const handleLibraryChange = (newLibraryId: string) => { - setCurrentLibraryId(newLibraryId); - }; + // Listen for library changes from client and update local state + useEffect(() => { + const handleLibraryChange = (newLibraryId: string) => { + setCurrentLibraryId(newLibraryId); + }; - client.on("library-changed", handleLibraryChange); - return () => { - client.off("library-changed", handleLibraryChange); - }; - }, [client]); + client.on('library-changed', handleLibraryChange); + return () => { + client.off('library-changed', handleLibraryChange); + }; + }, [client]); - // Auto-select first library on mount if none selected - useEffect(() => { - if (libraries && libraries.length > 0 && !currentLibraryId) { - const firstLib = libraries[0]; + // Auto-select first library on mount if none selected + useEffect(() => { + if (libraries && libraries.length > 0 && !currentLibraryId) { + const firstLib = libraries[0]; - // Set library ID via platform (syncs to all windows on Tauri) - if (platform.setCurrentLibraryId) { - platform.setCurrentLibraryId(firstLib.id).catch((err) => - console.error("Failed to set library ID:", err), - ); - } else { - // Web fallback - just update client - client.setCurrentLibrary(firstLib.id); - } - } - }, [libraries, currentLibraryId, client, platform]); + // Set library ID via platform (syncs to all windows on Tauri) + if (platform.setCurrentLibraryId) { + platform + .setCurrentLibraryId(firstLib.id) + .catch((err) => + console.error('Failed to set library ID:', err) + ); + } else { + // Web fallback - just update client + client.setCurrentLibrary(firstLib.id); + } + } + }, [libraries, currentLibraryId, client, platform]); - const handleLibrarySwitch = (libraryId: string) => { - // Set library ID via platform (syncs to all windows on Tauri) - if (platform.setCurrentLibraryId) { - platform.setCurrentLibraryId(libraryId).catch((err) => - console.error("Failed to set library ID:", err), - ); - } else { - // Web fallback - just update client - client.setCurrentLibrary(libraryId); - } - }; + const handleLibrarySwitch = (libraryId: string) => { + // Set library ID via platform (syncs to all windows on Tauri) + if (platform.setCurrentLibraryId) { + platform + .setCurrentLibraryId(libraryId) + .catch((err) => + console.error('Failed to set library ID:', err) + ); + } else { + // Web fallback - just update client + client.setCurrentLibrary(libraryId); + } + }; - const currentLibrary = libraries?.find((lib) => lib.id === currentLibraryId); + const currentLibrary = libraries?.find( + (lib) => lib.id === currentLibraryId + ); - return ( -
-
- +
+
+ ); +}