|
|
@@ -1,6 +1,5 @@
|
|
|
import type { FC } from 'react';
|
|
|
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
|
-import type { ItemInstance } from '@headless-tree/core';
|
|
|
import {
|
|
|
asyncDataLoaderFeature,
|
|
|
hotkeysCoreFeature,
|
|
|
@@ -16,11 +15,9 @@ import { useSWRxRootPage } from '~/stores/page-listing';
|
|
|
import { ROOT_PAGE_VIRTUAL_ID } from '../../constants';
|
|
|
import { useAutoExpandAncestors } from '../hooks/use-auto-expand-ancestors';
|
|
|
import { clearChildrenCache, useDataLoader } from '../hooks/use-data-loader';
|
|
|
-import { usePageCreate } from '../hooks/use-page-create';
|
|
|
-import { usePageRename } from '../hooks/use-page-rename';
|
|
|
import { useScrollToSelectedItem } from '../hooks/use-scroll-to-selected-item';
|
|
|
+import { useTreeItemHandlers } from '../hooks/use-tree-item-handlers';
|
|
|
import type { TreeItemProps } from '../interfaces';
|
|
|
-import { useCreatingParentId } from '../states/page-tree-create';
|
|
|
import {
|
|
|
usePageTreeInformationGeneration,
|
|
|
usePageTreeRevalidationEffect,
|
|
|
@@ -77,75 +74,16 @@ export const SimplifiedItemsTree: FC<Props> = (props: Props) => {
|
|
|
|
|
|
const dataLoader = useDataLoader(rootPageId, allPagesCount);
|
|
|
|
|
|
- // Page rename hook
|
|
|
- const { rename, getPageName } = usePageRename();
|
|
|
-
|
|
|
- // Page create hook
|
|
|
- const { createFromPlaceholder, isCreatingPlaceholder, cancelCreating } =
|
|
|
- usePageCreate();
|
|
|
-
|
|
|
- // Get creating parent id to determine if item should be treated as folder
|
|
|
- const creatingParentId = useCreatingParentId();
|
|
|
-
|
|
|
- // Use refs to stabilize callbacks passed to useTree
|
|
|
- // This prevents headless-tree from detecting config changes and refetching data
|
|
|
- const creatingParentIdRef = useRef(creatingParentId);
|
|
|
- creatingParentIdRef.current = creatingParentId;
|
|
|
-
|
|
|
- const getPageNameRef = useRef(getPageName);
|
|
|
- getPageNameRef.current = getPageName;
|
|
|
-
|
|
|
- const renameRef = useRef(rename);
|
|
|
- renameRef.current = rename;
|
|
|
-
|
|
|
- const createFromPlaceholderRef = useRef(createFromPlaceholder);
|
|
|
- createFromPlaceholderRef.current = createFromPlaceholder;
|
|
|
-
|
|
|
- const isCreatingPlaceholderRef = useRef(isCreatingPlaceholder);
|
|
|
- isCreatingPlaceholderRef.current = isCreatingPlaceholder;
|
|
|
-
|
|
|
- const cancelCreatingRef = useRef(cancelCreating);
|
|
|
- cancelCreatingRef.current = cancelCreating;
|
|
|
-
|
|
|
- // Stable getItemName callback - receives ItemInstance from headless-tree
|
|
|
- const getItemName = useCallback((item: ItemInstance<IPageForTreeItem>) => {
|
|
|
- return getPageNameRef.current(item);
|
|
|
- }, []);
|
|
|
-
|
|
|
- // Stable isItemFolder callback
|
|
|
- // IMPORTANT: Do NOT call item.getChildren() here as it triggers API calls for ALL visible items
|
|
|
- const isItemFolder = useCallback((item: ItemInstance<IPageForTreeItem>) => {
|
|
|
- const itemData = item.getItemData();
|
|
|
- const currentCreatingParentId = creatingParentIdRef.current;
|
|
|
- const isCreatingUnderThis = currentCreatingParentId === itemData._id;
|
|
|
- if (isCreatingUnderThis) return true;
|
|
|
-
|
|
|
- // Use descendantCount from the item data to determine if it's a folder
|
|
|
- // This avoids triggering getChildrenWithData API calls
|
|
|
- return itemData.descendantCount > 0;
|
|
|
+ // Tree item handlers (rename, create, etc.) with stable callbacks for headless-tree
|
|
|
+ const handleAfterRename = useCallback(() => {
|
|
|
+ setRebuildTrigger((prev) => prev + 1);
|
|
|
}, []);
|
|
|
-
|
|
|
- // Stable onRename handler for headless-tree
|
|
|
- // Handles both rename and create (for placeholder nodes)
|
|
|
- const handleRename = useCallback(
|
|
|
- async (item: ItemInstance<IPageForTreeItem>, newValue: string) => {
|
|
|
- if (isCreatingPlaceholderRef.current(item)) {
|
|
|
- // Placeholder node: create new page or cancel if empty
|
|
|
- if (newValue.trim() === '') {
|
|
|
- // Empty value means cancel (Esc key or blur)
|
|
|
- cancelCreatingRef.current();
|
|
|
- } else {
|
|
|
- await createFromPlaceholderRef.current(item, newValue);
|
|
|
- }
|
|
|
- } else {
|
|
|
- // Normal node: rename page
|
|
|
- await renameRef.current(item, newValue);
|
|
|
- }
|
|
|
- // Trigger re-render after operation
|
|
|
- setRebuildTrigger((prev) => prev + 1);
|
|
|
- },
|
|
|
- [],
|
|
|
- );
|
|
|
+ const {
|
|
|
+ getItemName,
|
|
|
+ isItemFolder,
|
|
|
+ handleRename,
|
|
|
+ creatingParentId,
|
|
|
+ } = useTreeItemHandlers(handleAfterRename);
|
|
|
|
|
|
// Stable initial state
|
|
|
const initialState = useMemo(() => ({ expandedItems: [ROOT_PAGE_VIRTUAL_ID] }), []);
|