70 lines
1.5 KiB
TypeScript
70 lines
1.5 KiB
TypeScript
import { Loader } from '@mantine/core';
|
|
import type { ReactNode } from 'react';
|
|
|
|
import styles from '../../styles/griddy.module.css';
|
|
|
|
interface TreeExpandButtonProps {
|
|
canExpand: boolean;
|
|
isExpanded: boolean;
|
|
isLoading?: boolean;
|
|
onToggle: () => void;
|
|
icons?: {
|
|
collapsed?: ReactNode;
|
|
expanded?: ReactNode;
|
|
leaf?: ReactNode;
|
|
};
|
|
}
|
|
|
|
const DEFAULT_ICONS = {
|
|
collapsed: '\u25B6', // ►
|
|
expanded: '\u25BC', // ▼
|
|
leaf: null,
|
|
};
|
|
|
|
export function TreeExpandButton({
|
|
canExpand,
|
|
isExpanded,
|
|
isLoading = false,
|
|
onToggle,
|
|
icons = DEFAULT_ICONS,
|
|
}: TreeExpandButtonProps) {
|
|
const displayIcons = { ...DEFAULT_ICONS, ...icons };
|
|
|
|
// If loading, show spinner
|
|
if (isLoading) {
|
|
return (
|
|
<button
|
|
className={styles['griddy-tree-expand-button']}
|
|
disabled
|
|
style={{ cursor: 'wait' }}
|
|
type="button"
|
|
>
|
|
<Loader size="xs" />
|
|
</button>
|
|
);
|
|
}
|
|
|
|
// If can't expand (leaf node), show leaf icon or empty space
|
|
if (!canExpand) {
|
|
return (
|
|
<span className={styles['griddy-tree-expand-button']} style={{ cursor: 'default' }}>
|
|
{displayIcons.leaf || <span style={{ width: 20 }} />}
|
|
</span>
|
|
);
|
|
}
|
|
|
|
// Show expand/collapse icon
|
|
return (
|
|
<button
|
|
className={styles['griddy-tree-expand-button']}
|
|
onClick={(e) => {
|
|
e.stopPropagation();
|
|
onToggle();
|
|
}}
|
|
type="button"
|
|
>
|
|
{isExpanded ? displayIcons.expanded : displayIcons.collapsed}
|
|
</button>
|
|
);
|
|
}
|