import { CheckSquare, FolderPlus, Square, } from 'lucide-react'; import type { Dispatch, PointerEvent as ReactPointerEvent, RefObject, SetStateAction, } from 'react'; import { useMemo, useState } from 'react'; import { PlatformTextField } from '../common/PlatformTextField'; import { filterGroupedAssetsBySearch, layerMatchesSearch, layerStartsWithSearch, } from './ImageCanvasAssetLibraryModel'; import { type GroupedEditorAssetFolder, ImageCanvasAssetLibraryPanelView, type UploadFilesOptions, type UploadRequestOptions, } from './ImageCanvasAssetLibraryPanelView'; import { EditorIconButton } from './ImageCanvasEditorPrimitives'; import type { AssetMarqueeState, AssetPointerDragState, CanvasContextMenuState, CanvasLayer, EditorAsset, EditorAssetFolder, ImageContextMenuState, SidebarPanel, UploadTarget, } from './ImageCanvasEditorTypes'; import { ImageCanvasLayerPanelView } from './ImageCanvasLayerPanelView'; export type { GroupedEditorAssetFolder, UploadFilesOptions }; export type ImageCanvasSidebarViewProps = { activeSidebarPanel: SidebarPanel | null; assetListRef: RefObject; assetPointerDragRef: { current: AssetPointerDragState | null }; suppressAssetClickRef: { current: boolean }; assets: EditorAsset[]; groupedAssets: GroupedEditorAssetFolder[]; assetFolders: EditorAssetFolder[]; layers: CanvasLayer[]; selectedLayerId: string | null; selectedLayerIds: string[]; isAssetSelectionMode: boolean; selectedAssetIds: Set; assetMoveDropFolderId: string | null; pinnedAssetMoveFolderId: string | null; creatingFolder: boolean; newFolderName: string; renamingFolder: { folderId: string; value: string } | null; renamingAsset: { assetId: string; value: string } | null; allSelectableAssetsSelected: boolean; assetMarquee: AssetMarqueeState | null; setIsAssetSelectionMode: Dispatch>; setCreatingFolder: Dispatch>; setNewFolderName: Dispatch>; setRenamingFolder: Dispatch< SetStateAction<{ folderId: string; value: string } | null> >; setRenamingAsset: Dispatch< SetStateAction<{ assetId: string; value: string } | null> >; setActiveUploadFolderId: Dispatch>; setUploadDropTarget: Dispatch>; setAssetPointerDrag: Dispatch>; setSelectedAssetIds: Dispatch>>; setImageContextMenu: Dispatch>; setContextMenu: Dispatch>; onAssetMarqueePointerDown: ( event: ReactPointerEvent, ) => void; onAssetMarqueePointerMove: ( event: ReactPointerEvent, ) => void; onAssetMarqueePointerUp: ( event: ReactPointerEvent, ) => void; updateAssetMoveDropFolder: (folderId: string | null) => void; addUploadedFiles: (files: FileList | File[], options?: UploadFilesOptions) => void; requestUpload: (target: UploadTarget, options?: UploadRequestOptions) => void; moveAssetToFolder: (assetId: string, folderId: string) => void; commitNewAssetFolder: () => void | Promise; toggleAssetFolder: (folderId: string) => void; startRenamingFolder: (folder: EditorAssetFolder) => void; commitFolderRename: (folder: EditorAssetFolder) => void; deleteAssetFolder: (folder: EditorAssetFolder) => void; startRenamingAsset: (asset: EditorAsset) => void; commitAssetRename: (asset: EditorAsset) => void; deleteUploadedAsset: (asset: EditorAsset) => void; submitAssetToShowcase: (asset: EditorAsset) => void; toggleAssetSelected: (assetId: string) => void; addAssetLayer: (asset: EditorAsset) => void; onDownloadAsset: (asset: EditorAsset) => void; toggleAllAssetsSelected: () => void; deleteSelectedAssets: () => void; closeAssetSelectionMode: () => void; groupSelectedLayers: () => void; selectSingleLayer: (layerId: string | null) => void; resolveContextMenuPosition: ( clientX: number, clientY: number, menuKind: 'blank' | 'layer', ) => Omit; getCanvasPointFromClient: ( clientX: number, clientY: number, ) => { x: number; y: number }; }; export function ImageCanvasSidebarView({ activeSidebarPanel, assetListRef, assetPointerDragRef, suppressAssetClickRef, groupedAssets, assetFolders, layers, selectedLayerId, selectedLayerIds, isAssetSelectionMode, selectedAssetIds, assetMoveDropFolderId, pinnedAssetMoveFolderId, creatingFolder, newFolderName, renamingFolder, renamingAsset, allSelectableAssetsSelected, assetMarquee, setIsAssetSelectionMode, setCreatingFolder, setNewFolderName, setRenamingFolder, setRenamingAsset, setActiveUploadFolderId, setUploadDropTarget, setAssetPointerDrag, setSelectedAssetIds, setImageContextMenu, setContextMenu, onAssetMarqueePointerDown, onAssetMarqueePointerMove, onAssetMarqueePointerUp, updateAssetMoveDropFolder, addUploadedFiles, requestUpload, moveAssetToFolder, commitNewAssetFolder, toggleAssetFolder, startRenamingFolder, commitFolderRename, deleteAssetFolder, startRenamingAsset, commitAssetRename, deleteUploadedAsset, submitAssetToShowcase, toggleAssetSelected, addAssetLayer, onDownloadAsset, toggleAllAssetsSelected, deleteSelectedAssets, closeAssetSelectionMode, groupSelectedLayers, selectSingleLayer, resolveContextMenuPosition, getCanvasPointFromClient, }: ImageCanvasSidebarViewProps) { const [assetSearchQuery, setAssetSearchQuery] = useState(''); const [layerSearchQuery, setLayerSearchQuery] = useState(''); const filteredGroupedAssets = useMemo( () => filterGroupedAssetsBySearch(groupedAssets, assetSearchQuery), [assetSearchQuery, groupedAssets], ); const filteredAssetsCount = useMemo( () => filteredGroupedAssets.reduce( (totalCount, folder) => totalCount + folder.assets.length, 0, ), [filteredGroupedAssets], ); const normalizedLayerSearchQuery = layerSearchQuery.trim().toLowerCase(); const filteredLayers = useMemo( () => normalizedLayerSearchQuery ? [ ...layers.filter((layer) => layerStartsWithSearch(layer, normalizedLayerSearchQuery), ), ...layers.filter( (layer) => !layerStartsWithSearch(layer, normalizedLayerSearchQuery) && layerMatchesSearch(layer, normalizedLayerSearchQuery), ), ] : layers, [layers, normalizedLayerSearchQuery], ); if (!activeSidebarPanel) { return null; } return ( ); }