import React, { useCallback, useEffect, useMemo, type MouseEvent, type JSX, } from 'react'; import { addTrailingSlash } from '@growi/core/dist/utils/path-utils'; import { usePageTreeDescCountMap } from '~/states/ui/page-tree-desc-count-map'; import { SimpleItemContent } from './SimpleItemContent'; import type { TreeItemProps, TreeItemToolProps } from './interfaces'; import styles from './TreeItemLayout.module.scss'; const moduleClass = styles['tree-item-layout'] ?? ''; type TreeItemLayoutProps = TreeItemProps & { className?: string, indentSize?: number, } export const TreeItemLayout = (props: TreeItemLayoutProps): JSX.Element => { const { className, itemClassName, indentSize = 10, item: page, itemLevel: baseItemLevel = 1, targetPath, targetPathOrId, isExpanded = false, isEnableActions, isReadOnlyUser, isWipPageShown = true, showAlternativeContent, onRenamed, onClick, onClickDuplicateMenuItem, onClickDeleteMenuItem, onWheelClick, onToggle, } = props; const itemClickHandler = useCallback((e: MouseEvent) => { // DO NOT handle the event when e.currentTarget and e.target is different if (e.target !== e.currentTarget) { return; } onClick?.(page); }, [onClick, page]); const itemMouseupHandler = useCallback((e: MouseEvent) => { // DO NOT handle the event when e.currentTarget and e.target is different if (e.target !== e.currentTarget) { return; } if (e.button === 1) { e.preventDefault(); onWheelClick?.(page); } }, [onWheelClick, page]); // descendantCount const { getDescCount } = usePageTreeDescCountMap(); const descendantCount = getDescCount(page._id) || page.descendantCount || 0; // hasDescendants flag const hasDescendants = descendantCount > 0; // auto open if targetPath is descendant of this page useEffect(() => { if (isExpanded) return; const isPathToTarget = page.path != null && targetPath.startsWith(addTrailingSlash(page.path)) && targetPath !== page.path; // Target Page does not need to be opened if (isPathToTarget) onToggle?.(); }, [targetPath, page.path, isExpanded, onToggle]); const isSelected = useMemo(() => { return page._id === targetPathOrId || page.path === targetPathOrId; }, [page, targetPathOrId]); const toolProps: TreeItemToolProps = { item: page, itemLevel: baseItemLevel, isEnableActions, isReadOnlyUser, onRenamed, onClickDuplicateMenuItem, onClickDeleteMenuItem, }; const EndComponents = props.customEndComponents; const HoveredEndComponents = props.customHoveredEndComponents; const AlternativeComponents = props.customAlternativeComponents; if (!isWipPageShown && page.wip) { return <>>; } return (