2024-06-21 19:27:51 +03:00
|
|
|
'use client';
|
|
|
|
|
2024-12-13 21:30:49 +03:00
|
|
|
import { useEffect, useState } from 'react';
|
2025-02-12 21:36:03 +03:00
|
|
|
import clsx from 'clsx';
|
2024-06-21 19:27:51 +03:00
|
|
|
|
2025-02-10 01:32:16 +03:00
|
|
|
import { MiniButton } from '@/components/Control';
|
2025-01-28 23:23:03 +03:00
|
|
|
import { IconFolder, IconFolderClosed, IconFolderEmpty, IconFolderOpened } from '@/components/Icons';
|
2025-02-20 20:22:05 +03:00
|
|
|
import { type EventMouse, type Styling } from '@/components/props';
|
2024-06-21 19:27:51 +03:00
|
|
|
|
2025-02-10 01:32:16 +03:00
|
|
|
import { useFolders } from '../backend/useFolders';
|
2025-02-11 20:56:11 +03:00
|
|
|
import { labelFolderNode } from '../labels';
|
2025-02-12 15:12:59 +03:00
|
|
|
import { FolderNode } from '../models/FolderTree';
|
2025-02-10 01:32:16 +03:00
|
|
|
|
2025-02-20 20:22:05 +03:00
|
|
|
interface SelectLocationProps extends Styling {
|
2024-06-21 19:27:51 +03:00
|
|
|
value: string;
|
2025-02-20 20:22:05 +03:00
|
|
|
onClick: (event: EventMouse, target: FolderNode) => void;
|
2025-02-04 20:35:18 +03:00
|
|
|
|
2024-06-26 18:59:49 +03:00
|
|
|
prefix: string;
|
|
|
|
dense?: boolean;
|
2024-06-21 19:27:51 +03:00
|
|
|
}
|
|
|
|
|
2025-02-19 23:29:45 +03:00
|
|
|
export function SelectLocation({ value, dense, prefix, onClick, className, style }: SelectLocationProps) {
|
2025-01-23 19:41:31 +03:00
|
|
|
const { folders } = useFolders();
|
|
|
|
const activeNode = folders.at(value);
|
|
|
|
const items = folders.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
|
|
|
|
2025-02-20 20:22:05 +03:00
|
|
|
function handleClickFold(event: EventMouse, target: FolderNode, showChildren: boolean) {
|
2024-12-13 21:30:49 +03:00
|
|
|
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>
|
|
|
|
);
|
|
|
|
}
|