2024-06-21 19:27:51 +03:00
|
|
|
'use client';
|
|
|
|
|
2024-06-26 18:59:49 +03:00
|
|
|
import clsx from 'clsx';
|
2024-12-13 21:30:49 +03:00
|
|
|
import { useEffect, useState } from 'react';
|
2024-06-21 19:27:51 +03:00
|
|
|
|
2024-06-26 18:59:49 +03:00
|
|
|
import { FolderNode, FolderTree } from '@/models/FolderTree';
|
|
|
|
import { labelFolderNode } from '@/utils/labels';
|
2024-06-21 19:27:51 +03:00
|
|
|
|
2024-06-26 18:59:49 +03:00
|
|
|
import { IconFolder, IconFolderClosed, IconFolderEmpty, IconFolderOpened } from '../Icons';
|
|
|
|
import { CProps } from '../props';
|
2024-06-21 19:27:51 +03:00
|
|
|
import MiniButton from '../ui/MiniButton';
|
|
|
|
|
2024-06-26 18:59:49 +03:00
|
|
|
interface SelectLocationProps extends CProps.Styling {
|
2024-06-21 19:27:51 +03:00
|
|
|
value: string;
|
|
|
|
folderTree: FolderTree;
|
2024-06-26 18:59:49 +03:00
|
|
|
prefix: string;
|
|
|
|
dense?: boolean;
|
|
|
|
onClick: (event: CProps.EventMouse, target: FolderNode) => void;
|
2024-06-21 19:27:51 +03:00
|
|
|
}
|
|
|
|
|
2024-06-26 18:59:49 +03:00
|
|
|
function SelectLocation({ value, folderTree, dense, prefix, onClick, className, style }: SelectLocationProps) {
|
2024-12-13 21:30:49 +03:00
|
|
|
const activeNode = folderTree.at(value);
|
|
|
|
const items = folderTree.getTree();
|
2024-06-26 18:59:49 +03:00
|
|
|
const [folded, setFolded] = useState<FolderNode[]>(items);
|
|
|
|
|
2024-12-12 20:57:45 +03:00
|
|
|
useEffect(() => {
|
2024-08-06 14:38:10 +03:00
|
|
|
setFolded(items.filter(item => item !== activeNode && !activeNode?.hasPredecessor(item)));
|
2024-06-26 18:59:49 +03:00
|
|
|
}, [items, activeNode]);
|
|
|
|
|
2024-12-13 21:30:49 +03:00
|
|
|
function onFoldItem(target: FolderNode, showChildren: boolean) {
|
|
|
|
setFolded(prev =>
|
|
|
|
items.filter(item => {
|
|
|
|
if (item === target) {
|
|
|
|
return !showChildren;
|
|
|
|
}
|
|
|
|
if (!showChildren && item.hasPredecessor(target)) {
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
return prev.includes(item);
|
|
|
|
}
|
|
|
|
})
|
|
|
|
);
|
|
|
|
}
|
2024-06-21 19:27:51 +03:00
|
|
|
|
2024-12-13 21:30:49 +03:00
|
|
|
function handleClickFold(event: CProps.EventMouse, target: FolderNode, showChildren: boolean) {
|
|
|
|
event.preventDefault();
|
|
|
|
event.stopPropagation();
|
|
|
|
onFoldItem(target, showChildren);
|
|
|
|
}
|
2024-06-21 19:27:51 +03:00
|
|
|
|
|
|
|
return (
|
2024-06-26 18:59:49 +03:00
|
|
|
<div className={clsx('flex flex-col', 'cc-scroll-y', className)} style={style}>
|
|
|
|
{items.map((item, index) =>
|
|
|
|
!item.parent || !folded.includes(item.parent) ? (
|
|
|
|
<div
|
|
|
|
tabIndex={-1}
|
|
|
|
key={`${prefix}${index}`}
|
|
|
|
className={clsx(
|
|
|
|
!dense && 'min-h-[2.0825rem] sm:min-h-[2.3125rem]',
|
|
|
|
'pr-3 py-1 flex items-center gap-2',
|
|
|
|
'cc-scroll-row',
|
2024-12-17 11:37:42 +03:00
|
|
|
'clr-hover cc-animate-color',
|
2024-06-26 18:59:49 +03:00
|
|
|
'cursor-pointer',
|
|
|
|
'leading-3 sm:leading-4',
|
|
|
|
activeNode === item && 'clr-selected'
|
|
|
|
)}
|
|
|
|
style={{ paddingLeft: `${(item.rank > 5 ? 5 : item.rank) * 0.5 + 0.5}rem` }}
|
|
|
|
onClick={event => onClick(event, item)}
|
|
|
|
>
|
|
|
|
{item.children.size > 0 ? (
|
|
|
|
<MiniButton
|
|
|
|
noPadding
|
|
|
|
noHover
|
|
|
|
icon={
|
|
|
|
folded.includes(item) ? (
|
|
|
|
item.filesInside ? (
|
|
|
|
<IconFolderClosed size='1rem' className='icon-primary' />
|
|
|
|
) : (
|
|
|
|
<IconFolderEmpty size='1rem' className='icon-primary' />
|
|
|
|
)
|
|
|
|
) : (
|
|
|
|
<IconFolderOpened size='1rem' className='icon-green' />
|
|
|
|
)
|
|
|
|
}
|
|
|
|
onClick={event => handleClickFold(event, item, folded.includes(item))}
|
|
|
|
/>
|
|
|
|
) : (
|
|
|
|
<div>
|
|
|
|
{item.filesInside ? (
|
|
|
|
<IconFolder size='1rem' className='clr-text-default' />
|
|
|
|
) : (
|
|
|
|
<IconFolderEmpty size='1rem' className='clr-text-controls' />
|
|
|
|
)}
|
|
|
|
</div>
|
|
|
|
)}
|
|
|
|
<div className='self-center text-start'>{labelFolderNode(item)}</div>
|
|
|
|
</div>
|
|
|
|
) : null
|
|
|
|
)}
|
2024-06-21 19:27:51 +03:00
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
export default SelectLocation;
|