mirror of
https://github.com/spacedriveapp/spacedrive
synced 2024-07-19 14:49:11 +00:00
parent
e314943c3b
commit
f37c6b3600
|
@ -1,14 +1,13 @@
|
|||
import clsx from 'clsx';
|
||||
import { Columns, GridFour, Icon, MonitorPlay, Rows } from 'phosphor-react';
|
||||
import {
|
||||
Cards,
|
||||
Columns,
|
||||
FolderNotchOpen,
|
||||
GridFour,
|
||||
MonitorPlay,
|
||||
Rows,
|
||||
SquaresFour
|
||||
} from 'phosphor-react';
|
||||
import { HTMLAttributes, PropsWithChildren, ReactNode, memo, useState } from 'react';
|
||||
HTMLAttributes,
|
||||
PropsWithChildren,
|
||||
ReactNode,
|
||||
isValidElement,
|
||||
memo,
|
||||
useState
|
||||
} from 'react';
|
||||
import { createSearchParams, useNavigate } from 'react-router-dom';
|
||||
import { useKey } from 'rooks';
|
||||
import { ExplorerItem, isPath, useLibraryContext, useLibraryMutation } from '@sd/client';
|
||||
|
@ -81,11 +80,11 @@ export const ViewItem = ({ data, children, ...props }: ViewItemProps) => {
|
|||
);
|
||||
};
|
||||
|
||||
interface Props<T extends ExplorerViewSelection>
|
||||
export interface ExplorerViewProps<T extends ExplorerViewSelection = ExplorerViewSelection>
|
||||
extends Omit<ExplorerViewContext<T>, 'multiSelect' | 'selectable'> {
|
||||
layout: ExplorerLayoutMode;
|
||||
className?: string;
|
||||
emptyNotice?: ReactNode;
|
||||
emptyNotice?: JSX.Element | { icon?: Icon | ReactNode; message?: ReactNode } | null;
|
||||
}
|
||||
|
||||
export default memo(({ layout, className, emptyNotice, ...contextProps }) => {
|
||||
|
@ -111,22 +110,24 @@ export default memo(({ layout, className, emptyNotice, ...contextProps }) => {
|
|||
}
|
||||
});
|
||||
|
||||
const emptyNoticeIcon = () => {
|
||||
let Icon;
|
||||
const emptyNoticeIcon = (icon?: Icon) => {
|
||||
let Icon = icon;
|
||||
|
||||
switch (layout) {
|
||||
case 'grid':
|
||||
Icon = GridFour;
|
||||
break;
|
||||
case 'media':
|
||||
Icon = MonitorPlay;
|
||||
break;
|
||||
case 'columns':
|
||||
Icon = Columns;
|
||||
break;
|
||||
case 'rows':
|
||||
Icon = Rows;
|
||||
break;
|
||||
if (!Icon) {
|
||||
switch (layout) {
|
||||
case 'grid':
|
||||
Icon = GridFour;
|
||||
break;
|
||||
case 'media':
|
||||
Icon = MonitorPlay;
|
||||
break;
|
||||
case 'columns':
|
||||
Icon = Columns;
|
||||
break;
|
||||
case 'rows':
|
||||
Icon = Rows;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return <Icon size={100} opacity={0.3} />;
|
||||
|
@ -150,14 +151,23 @@ export default memo(({ layout, className, emptyNotice, ...contextProps }) => {
|
|||
{layout === 'rows' && <ListView />}
|
||||
{layout === 'media' && <MediaView />}
|
||||
</ViewContext.Provider>
|
||||
) : emptyNotice === null ? null : (
|
||||
emptyNotice || (
|
||||
<div className="flex h-full flex-col items-center justify-center text-ink-faint">
|
||||
{emptyNoticeIcon()}
|
||||
<p className="mt-5 text-xs">This list is empty</p>
|
||||
</div>
|
||||
)
|
||||
) : emptyNotice === null ? null : isValidElement(emptyNotice) ? (
|
||||
emptyNotice
|
||||
) : (
|
||||
<div className="flex h-full flex-col items-center justify-center text-ink-faint">
|
||||
{emptyNotice && 'icon' in emptyNotice
|
||||
? isValidElement(emptyNotice.icon)
|
||||
? emptyNotice.icon
|
||||
: emptyNoticeIcon(emptyNotice.icon as Icon)
|
||||
: emptyNoticeIcon()}
|
||||
|
||||
<p className="mt-5 text-xs">
|
||||
{emptyNotice && 'message' in emptyNotice
|
||||
? emptyNotice.message
|
||||
: 'This list is empty'}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}) as <T extends ExplorerViewSelection>(props: Props<T>) => JSX.Element;
|
||||
}) as <T extends ExplorerViewSelection>(props: ExplorerViewProps<T>) => JSX.Element;
|
||||
|
|
|
@ -7,12 +7,13 @@ import ExplorerContextMenu from './ContextMenu';
|
|||
import DismissibleNotice from './DismissibleNotice';
|
||||
import ContextMenu from './File/ContextMenu';
|
||||
import { Inspector } from './Inspector';
|
||||
import View from './View';
|
||||
import View, { ExplorerViewProps } from './View';
|
||||
import { useExplorerSearchParams } from './util';
|
||||
|
||||
interface Props {
|
||||
items: ExplorerItem[] | null;
|
||||
onLoadMore?(): void;
|
||||
emptyNotice?: ExplorerViewProps['emptyNotice'];
|
||||
}
|
||||
|
||||
export default function Explorer(props: Props) {
|
||||
|
@ -74,10 +75,10 @@ export default function Explorer(props: Props) {
|
|||
onSelectedChange={setSelectedItemId}
|
||||
contextMenu={<ContextMenu data={selectedItem} />}
|
||||
emptyNotice={
|
||||
<div className="flex h-full flex-col items-center justify-center text-ink-faint">
|
||||
<FolderNotchOpen size={100} opacity={0.3} />
|
||||
<p className="mt-5 text-xs">This folder is empty</p>
|
||||
</div>
|
||||
props.emptyNotice || {
|
||||
icon: FolderNotchOpen,
|
||||
message: 'This folder is empty'
|
||||
}
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -36,7 +36,12 @@ export const Component = () => {
|
|||
/>
|
||||
}
|
||||
/>
|
||||
{explorerData.data && <Explorer items={explorerData.data.items} />}
|
||||
<Explorer
|
||||
items={explorerData.data?.items || null}
|
||||
emptyNotice={{
|
||||
message: 'No items assigned to this tag'
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue