import type { ChangeEvent, JSX } from 'react'; import { useState, useCallback, memo, } from 'react'; import nodePath from 'path'; import type { IPagePopulatedToShowRevision } from '@growi/core'; import { DevidedPagePath } from '@growi/core/dist/models'; import { normalizePath } from '@growi/core/dist/utils/path-utils'; import { useTranslation } from 'next-i18next'; import { debounce } from 'throttle-debounce'; import type { InputValidationResult } from '~/client/util/use-input-validator'; import { ValidationTarget, useInputValidator } from '~/client/util/use-input-validator'; import type { IPageForItem } from '~/interfaces/page'; import LinkedPagePath from '~/models/linked-page-path'; import { usePageSelectModal } from '~/stores/modal'; import { PagePathHierarchicalLink } from '../../../components/Common/PagePathHierarchicalLink'; import { AutosizeSubmittableInput, getAdjustedMaxWidthForAutosizeInput } from '../Common/SubmittableInput'; import { usePagePathRenameHandler } from '../PageEditor/page-path-rename-utils'; import styles from './PagePathHeader.module.scss'; const moduleClass = styles['page-path-header']; type Props = { currentPage: IPagePopulatedToShowRevision, className?: string, maxWidth?: number, onRenameTerminated?: () => void, } export const PagePathHeader = memo((props: Props): JSX.Element => { const { t } = useTranslation(); const { currentPage, className, maxWidth, onRenameTerminated, } = props; const dPagePath = new DevidedPagePath(currentPage.path, true); const parentPagePath = dPagePath.former; const linkedPagePath = new LinkedPagePath(parentPagePath); const [isRenameInputShown, setRenameInputShown] = useState(false); const [isHover, setHover] = useState(false); const { open: openPageSelectModal } = usePageSelectModal(); const [validationResult, setValidationResult] = useState(); const inputValidator = useInputValidator(ValidationTarget.PAGE); const changeHandler = useCallback(async(e: ChangeEvent) => { const validationResult = inputValidator(e.target.value); setValidationResult(validationResult ?? undefined); }, [inputValidator]); const changeHandlerDebounced = debounce(300, changeHandler); const pagePathRenameHandler = usePagePathRenameHandler(currentPage); const onClickOpenPageSelectModalButton = useCallback(() => { const onSelected = (page: IPageForItem): void => { if (page == null || page.path == null) { return; } const currentPageTitle = nodePath.basename(currentPage?.path ?? '') || '/'; const newPagePath = nodePath.resolve(page.path, currentPageTitle); pagePathRenameHandler(newPagePath); }; openPageSelectModal({ onSelected }); }, [currentPage?.path, openPageSelectModal, pagePathRenameHandler]); const rename = useCallback((inputText) => { const pathToRename = normalizePath(`${inputText}/${dPagePath.latter}`); pagePathRenameHandler(pathToRename, () => { setRenameInputShown(false); setValidationResult(undefined); onRenameTerminated?.(); }, () => { setRenameInputShown(true); }); }, [dPagePath.latter, pagePathRenameHandler, onRenameTerminated]); const cancel = useCallback(() => { // reset setValidationResult(undefined); setRenameInputShown(false); }, []); const onClickEditButton = useCallback(() => { // reset setRenameInputShown(true); }, []); if (dPagePath.isRoot) { return <>; } const isInvalid = validationResult != null; const inputMaxWidth = maxWidth != null ? getAdjustedMaxWidthForAutosizeInput(maxWidth, 'sm', validationResult != null ? false : undefined) - 16 : undefined; return (
setHover(true)} onMouseLeave={() => setHover(false)} >
{ isRenameInputShown && (
) }
); });